@sip-protocol/sdk 0.3.2 → 0.5.0
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/dist/browser.d.mts +2 -2
- package/dist/browser.d.ts +2 -2
- package/dist/browser.js +2881 -295
- package/dist/browser.mjs +62 -2
- package/dist/chunk-AOZIY3GU.mjs +12995 -0
- package/dist/chunk-BCLIX5T2.mjs +12940 -0
- package/dist/chunk-DMHBKRWV.mjs +14712 -0
- package/dist/chunk-FKXPHKYD.mjs +12955 -0
- package/dist/chunk-HGU6HZRC.mjs +231 -0
- package/dist/chunk-J4Q4NJ2U.mjs +13544 -0
- package/dist/chunk-OPQ2GQIO.mjs +13013 -0
- package/dist/chunk-W2B7T6WU.mjs +14714 -0
- package/dist/index-5jAdWMA-.d.ts +8973 -0
- package/dist/index-B9Vkpaao.d.mts +8973 -0
- package/dist/index-BcWNakUD.d.ts +7990 -0
- package/dist/index-BsKY3Hr0.d.mts +7990 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2852 -266
- package/dist/index.mjs +62 -2
- package/dist/proofs/noir.mjs +1 -1
- package/package.json +2 -1
- package/src/adapters/near-intents.ts +8 -0
- package/src/bitcoin/index.ts +51 -0
- package/src/bitcoin/silent-payments.ts +865 -0
- package/src/bitcoin/taproot.ts +590 -0
- package/src/compliance/compliance-manager.ts +87 -0
- package/src/compliance/conditional-threshold.ts +379 -0
- package/src/compliance/conditional.ts +382 -0
- package/src/compliance/derivation.ts +489 -0
- package/src/compliance/index.ts +50 -8
- package/src/compliance/pdf.ts +365 -0
- package/src/compliance/reports.ts +644 -0
- package/src/compliance/threshold.ts +529 -0
- package/src/compliance/types.ts +223 -0
- package/src/cosmos/ibc-stealth.ts +825 -0
- package/src/cosmos/index.ts +83 -0
- package/src/cosmos/stealth.ts +487 -0
- package/src/errors.ts +8 -0
- package/src/index.ts +80 -1
- package/src/move/aptos.ts +369 -0
- package/src/move/index.ts +35 -0
- package/src/move/sui.ts +367 -0
- package/src/oracle/types.ts +8 -0
- package/src/settlement/backends/direct-chain.ts +8 -0
- package/src/stealth.ts +3 -3
- package/src/validation.ts +42 -1
- package/src/wallet/aptos/adapter.ts +422 -0
- package/src/wallet/aptos/index.ts +10 -0
- package/src/wallet/aptos/mock.ts +410 -0
- package/src/wallet/aptos/types.ts +278 -0
- package/src/wallet/bitcoin/adapter.ts +470 -0
- package/src/wallet/bitcoin/index.ts +38 -0
- package/src/wallet/bitcoin/mock.ts +516 -0
- package/src/wallet/bitcoin/types.ts +274 -0
- package/src/wallet/cosmos/adapter.ts +484 -0
- package/src/wallet/cosmos/index.ts +63 -0
- package/src/wallet/cosmos/mock.ts +596 -0
- package/src/wallet/cosmos/types.ts +462 -0
- package/src/wallet/index.ts +127 -0
- package/src/wallet/sui/adapter.ts +471 -0
- package/src/wallet/sui/index.ts +10 -0
- package/src/wallet/sui/mock.ts +439 -0
- package/src/wallet/sui/types.ts +245 -0
package/dist/index.js
CHANGED
|
@@ -31,9 +31,16 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
ATTESTATION_VERSION: () => ATTESTATION_VERSION,
|
|
34
|
+
AptosStealthService: () => AptosStealthService,
|
|
35
|
+
AuditorKeyDerivation: () => AuditorKeyDerivation,
|
|
36
|
+
AuditorType: () => AuditorType,
|
|
34
37
|
BaseWalletAdapter: () => BaseWalletAdapter,
|
|
35
38
|
CHAIN_NUMERIC_IDS: () => CHAIN_NUMERIC_IDS,
|
|
39
|
+
COSMOS_CHAIN_PREFIXES: () => CHAIN_PREFIXES,
|
|
36
40
|
ComplianceManager: () => ComplianceManager,
|
|
41
|
+
ComplianceReporter: () => ComplianceReporter,
|
|
42
|
+
ConditionalDisclosure: () => ConditionalDisclosure,
|
|
43
|
+
CosmosStealthService: () => CosmosStealthService,
|
|
37
44
|
CryptoError: () => CryptoError,
|
|
38
45
|
DEFAULT_THRESHOLD: () => DEFAULT_THRESHOLD,
|
|
39
46
|
DEFAULT_TOTAL_ORACLES: () => DEFAULT_TOTAL_ORACLES,
|
|
@@ -46,7 +53,7 @@ __export(index_exports, {
|
|
|
46
53
|
HardwareWalletError: () => HardwareWalletError,
|
|
47
54
|
IntentBuilder: () => IntentBuilder,
|
|
48
55
|
IntentError: () => IntentError,
|
|
49
|
-
IntentStatus: () =>
|
|
56
|
+
IntentStatus: () => import_types55.IntentStatus,
|
|
50
57
|
LedgerWalletAdapter: () => LedgerWalletAdapter,
|
|
51
58
|
MockEthereumAdapter: () => MockEthereumAdapter,
|
|
52
59
|
MockLedgerAdapter: () => MockLedgerAdapter,
|
|
@@ -55,27 +62,27 @@ __export(index_exports, {
|
|
|
55
62
|
MockSolver: () => MockSolver,
|
|
56
63
|
MockTrezorAdapter: () => MockTrezorAdapter,
|
|
57
64
|
MockWalletAdapter: () => MockWalletAdapter,
|
|
58
|
-
NATIVE_TOKENS: () =>
|
|
65
|
+
NATIVE_TOKENS: () => import_types55.NATIVE_TOKENS,
|
|
59
66
|
NEARIntentsAdapter: () => NEARIntentsAdapter,
|
|
60
67
|
NEARIntentsBackend: () => NEARIntentsBackend,
|
|
61
68
|
NetworkError: () => NetworkError,
|
|
62
69
|
ORACLE_DOMAIN: () => ORACLE_DOMAIN,
|
|
63
70
|
OneClickClient: () => OneClickClient,
|
|
64
|
-
OneClickDepositMode: () =>
|
|
65
|
-
OneClickErrorCode: () =>
|
|
66
|
-
OneClickSwapStatus: () =>
|
|
67
|
-
OneClickSwapType: () =>
|
|
71
|
+
OneClickDepositMode: () => import_types59.OneClickDepositMode,
|
|
72
|
+
OneClickErrorCode: () => import_types59.OneClickErrorCode,
|
|
73
|
+
OneClickSwapStatus: () => import_types59.OneClickSwapStatus,
|
|
74
|
+
OneClickSwapType: () => import_types59.OneClickSwapType,
|
|
68
75
|
PaymentBuilder: () => PaymentBuilder,
|
|
69
|
-
PaymentStatus: () =>
|
|
70
|
-
PrivacyLevel: () =>
|
|
76
|
+
PaymentStatus: () => import_types56.PaymentStatus,
|
|
77
|
+
PrivacyLevel: () => import_types55.PrivacyLevel,
|
|
71
78
|
ProofError: () => ProofError,
|
|
72
79
|
ProofGenerationError: () => ProofGenerationError,
|
|
73
80
|
ProofNotImplementedError: () => ProofNotImplementedError,
|
|
74
|
-
ProposalStatus: () =>
|
|
75
|
-
ReportStatus: () =>
|
|
81
|
+
ProposalStatus: () => import_types57.ProposalStatus,
|
|
82
|
+
ReportStatus: () => import_types58.ReportStatus,
|
|
76
83
|
SIP: () => SIP,
|
|
77
84
|
SIPError: () => SIPError,
|
|
78
|
-
SIP_VERSION: () =>
|
|
85
|
+
SIP_VERSION: () => import_types55.SIP_VERSION,
|
|
79
86
|
STABLECOIN_ADDRESSES: () => STABLECOIN_ADDRESSES,
|
|
80
87
|
STABLECOIN_DECIMALS: () => STABLECOIN_DECIMALS,
|
|
81
88
|
STABLECOIN_INFO: () => STABLECOIN_INFO,
|
|
@@ -84,12 +91,13 @@ __export(index_exports, {
|
|
|
84
91
|
SmartRouter: () => SmartRouter,
|
|
85
92
|
SolanaWalletAdapter: () => SolanaWalletAdapter,
|
|
86
93
|
SwapStatus: () => SwapStatus,
|
|
94
|
+
ThresholdViewingKey: () => ThresholdViewingKey,
|
|
87
95
|
Treasury: () => Treasury,
|
|
88
96
|
TrezorWalletAdapter: () => TrezorWalletAdapter,
|
|
89
97
|
ValidationError: () => ValidationError,
|
|
90
98
|
WalletError: () => WalletError,
|
|
91
|
-
WalletErrorCode: () =>
|
|
92
|
-
ZcashErrorCode: () =>
|
|
99
|
+
WalletErrorCode: () => import_types54.WalletErrorCode,
|
|
100
|
+
ZcashErrorCode: () => import_types60.ZcashErrorCode,
|
|
93
101
|
ZcashNativeBackend: () => ZcashNativeBackend,
|
|
94
102
|
ZcashRPCClient: () => ZcashRPCClient,
|
|
95
103
|
ZcashRPCError: () => ZcashRPCError,
|
|
@@ -98,17 +106,21 @@ __export(index_exports, {
|
|
|
98
106
|
addBlindings: () => addBlindings,
|
|
99
107
|
addCommitments: () => addCommitments,
|
|
100
108
|
addOracle: () => addOracle,
|
|
109
|
+
aptosAddressToAuthKey: () => aptosAddressToAuthKey,
|
|
101
110
|
attachProofs: () => attachProofs,
|
|
102
111
|
base58ToHex: () => base58ToHex,
|
|
103
|
-
browserBytesToHex: () =>
|
|
104
|
-
browserHexToBytes: () =>
|
|
112
|
+
browserBytesToHex: () => bytesToHex11,
|
|
113
|
+
browserHexToBytes: () => hexToBytes9,
|
|
114
|
+
checkAptosStealthAddress: () => checkAptosStealthAddress,
|
|
105
115
|
checkEd25519StealthAddress: () => checkEd25519StealthAddress,
|
|
106
116
|
checkStealthAddress: () => checkStealthAddress,
|
|
107
117
|
commit: () => commit,
|
|
108
118
|
commitZero: () => commitZero,
|
|
109
119
|
computeAttestationHash: () => computeAttestationHash,
|
|
120
|
+
computeTweakedKey: () => computeTweakedKey,
|
|
110
121
|
createCommitment: () => createCommitment,
|
|
111
122
|
createEthereumAdapter: () => createEthereumAdapter,
|
|
123
|
+
createKeySpendOnlyOutput: () => createKeySpendOnlyOutput,
|
|
112
124
|
createLedgerAdapter: () => createLedgerAdapter,
|
|
113
125
|
createMockEthereumAdapter: () => createMockEthereumAdapter,
|
|
114
126
|
createMockEthereumProvider: () => createMockEthereumProvider,
|
|
@@ -127,6 +139,7 @@ __export(index_exports, {
|
|
|
127
139
|
createShieldedPayment: () => createShieldedPayment,
|
|
128
140
|
createSmartRouter: () => createSmartRouter,
|
|
129
141
|
createSolanaAdapter: () => createSolanaAdapter,
|
|
142
|
+
createTaprootOutput: () => createTaprootOutput,
|
|
130
143
|
createTrezorAdapter: () => createTrezorAdapter,
|
|
131
144
|
createWalletFactory: () => createWalletFactory,
|
|
132
145
|
createZcashClient: () => createZcashClient,
|
|
@@ -134,8 +147,10 @@ __export(index_exports, {
|
|
|
134
147
|
createZcashShieldedService: () => createZcashShieldedService,
|
|
135
148
|
createZcashSwapService: () => createZcashSwapService,
|
|
136
149
|
decodeStealthMetaAddress: () => decodeStealthMetaAddress,
|
|
150
|
+
decodeTaprootAddress: () => decodeTaprootAddress,
|
|
137
151
|
decryptMemo: () => decryptMemo,
|
|
138
152
|
decryptWithViewing: () => decryptWithViewing,
|
|
153
|
+
deriveAptosStealthPrivateKey: () => deriveAptosStealthPrivateKey,
|
|
139
154
|
deriveEd25519StealthPrivateKey: () => deriveEd25519StealthPrivateKey,
|
|
140
155
|
deriveOracleId: () => deriveOracleId,
|
|
141
156
|
deriveStealthPrivateKey: () => deriveStealthPrivateKey,
|
|
@@ -145,6 +160,7 @@ __export(index_exports, {
|
|
|
145
160
|
deserializePayment: () => deserializePayment,
|
|
146
161
|
detectEthereumWallets: () => detectEthereumWallets,
|
|
147
162
|
detectSolanaWallets: () => detectSolanaWallets,
|
|
163
|
+
ed25519PublicKeyToAptosAddress: () => ed25519PublicKeyToAptosAddress,
|
|
148
164
|
ed25519PublicKeyToNearAddress: () => ed25519PublicKeyToNearAddress,
|
|
149
165
|
ed25519PublicKeyToSolanaAddress: () => ed25519PublicKeyToSolanaAddress,
|
|
150
166
|
encodeStealthMetaAddress: () => encodeStealthMetaAddress,
|
|
@@ -153,10 +169,14 @@ __export(index_exports, {
|
|
|
153
169
|
formatStablecoinAmount: () => formatStablecoinAmount,
|
|
154
170
|
fromHex: () => fromHex,
|
|
155
171
|
fromStablecoinUnits: () => fromStablecoinUnits,
|
|
172
|
+
generateAptosStealthAddress: () => generateAptosStealthAddress,
|
|
156
173
|
generateBlinding: () => generateBlinding,
|
|
174
|
+
generateCosmosStealthAddress: () => generateCosmosStealthAddress,
|
|
175
|
+
generateCosmosStealthMetaAddress: () => generateCosmosStealthMetaAddress,
|
|
157
176
|
generateEd25519StealthAddress: () => generateEd25519StealthAddress,
|
|
158
177
|
generateEd25519StealthMetaAddress: () => generateEd25519StealthMetaAddress,
|
|
159
178
|
generateIntentId: () => generateIntentId,
|
|
179
|
+
generatePdfReport: () => generatePdfReport,
|
|
160
180
|
generateRandomBytes: () => generateRandomBytes,
|
|
161
181
|
generateStealthAddress: () => generateStealthAddress,
|
|
162
182
|
generateStealthMetaAddress: () => generateStealthMetaAddress,
|
|
@@ -183,6 +203,7 @@ __export(index_exports, {
|
|
|
183
203
|
getStablecoinsForChain: () => getStablecoinsForChain,
|
|
184
204
|
getSupportedStablecoins: () => getSupportedStablecoins,
|
|
185
205
|
getTimeRemaining: () => getTimeRemaining,
|
|
206
|
+
getXOnlyPublicKey: () => getXOnlyPublicKey,
|
|
186
207
|
hasEnoughOracles: () => hasEnoughOracles,
|
|
187
208
|
hasErrorCode: () => hasErrorCode,
|
|
188
209
|
hasRequiredProofs: () => hasRequiredProofs,
|
|
@@ -193,14 +214,16 @@ __export(index_exports, {
|
|
|
193
214
|
isExpired: () => isExpired,
|
|
194
215
|
isNonNegativeAmount: () => isNonNegativeAmount,
|
|
195
216
|
isPaymentExpired: () => isPaymentExpired,
|
|
196
|
-
isPrivate: () =>
|
|
217
|
+
isPrivate: () => import_types55.isPrivate,
|
|
197
218
|
isPrivateWalletAdapter: () => isPrivateWalletAdapter,
|
|
198
219
|
isSIPError: () => isSIPError,
|
|
199
220
|
isStablecoin: () => isStablecoin,
|
|
200
221
|
isStablecoinOnChain: () => isStablecoinOnChain,
|
|
201
222
|
isValidAmount: () => isValidAmount,
|
|
223
|
+
isValidAptosAddress: () => isValidAptosAddress,
|
|
202
224
|
isValidChainId: () => isValidChainId,
|
|
203
225
|
isValidCompressedPublicKey: () => isValidCompressedPublicKey,
|
|
226
|
+
isValidCosmosAddress: () => isValidCosmosAddress,
|
|
204
227
|
isValidEd25519PublicKey: () => isValidEd25519PublicKey,
|
|
205
228
|
isValidHex: () => isValidHex,
|
|
206
229
|
isValidHexLength: () => isValidHexLength,
|
|
@@ -212,12 +235,17 @@ __export(index_exports, {
|
|
|
212
235
|
isValidSlippage: () => isValidSlippage,
|
|
213
236
|
isValidSolanaAddress: () => isValidSolanaAddress,
|
|
214
237
|
isValidStealthMetaAddress: () => isValidStealthMetaAddress,
|
|
238
|
+
isValidTaprootAddress: () => isValidTaprootAddress,
|
|
215
239
|
nearAddressToEd25519PublicKey: () => nearAddressToEd25519PublicKey,
|
|
216
240
|
normalizeAddress: () => normalizeAddress,
|
|
217
241
|
notConnectedError: () => notConnectedError,
|
|
218
242
|
publicKeyToEthAddress: () => publicKeyToEthAddress,
|
|
219
243
|
registerWallet: () => registerWallet,
|
|
220
244
|
removeOracle: () => removeOracle,
|
|
245
|
+
schnorrSign: () => schnorrSign,
|
|
246
|
+
schnorrSignHex: () => schnorrSignHex,
|
|
247
|
+
schnorrVerify: () => schnorrVerify,
|
|
248
|
+
schnorrVerifyHex: () => schnorrVerifyHex,
|
|
221
249
|
secureWipe: () => secureWipe,
|
|
222
250
|
secureWipeAll: () => secureWipeAll,
|
|
223
251
|
serializeAttestationMessage: () => serializeAttestationMessage,
|
|
@@ -226,14 +254,16 @@ __export(index_exports, {
|
|
|
226
254
|
signAttestationMessage: () => signAttestationMessage,
|
|
227
255
|
solanaAddressToEd25519PublicKey: () => solanaAddressToEd25519PublicKey,
|
|
228
256
|
solanaPublicKeyToHex: () => solanaPublicKeyToHex,
|
|
257
|
+
stealthKeyToCosmosAddress: () => stealthKeyToCosmosAddress,
|
|
229
258
|
subtractBlindings: () => subtractBlindings,
|
|
230
259
|
subtractCommitments: () => subtractCommitments,
|
|
231
260
|
supportsSharedArrayBuffer: () => supportsSharedArrayBuffer,
|
|
232
|
-
supportsViewingKey: () =>
|
|
261
|
+
supportsViewingKey: () => import_types55.supportsViewingKey,
|
|
233
262
|
supportsWebBluetooth: () => supportsWebBluetooth,
|
|
234
263
|
supportsWebHID: () => supportsWebHID,
|
|
235
264
|
supportsWebUSB: () => supportsWebUSB,
|
|
236
265
|
supportsWebWorkers: () => supportsWebWorkers,
|
|
266
|
+
taprootAddress: () => taprootAddress,
|
|
237
267
|
toHex: () => toHex,
|
|
238
268
|
toStablecoinUnits: () => toStablecoinUnits,
|
|
239
269
|
trackIntent: () => trackIntent,
|
|
@@ -279,6 +309,14 @@ var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => {
|
|
|
279
309
|
ErrorCode2["SIGNATURE_FAILED"] = "SIP_3005";
|
|
280
310
|
ErrorCode2["INVALID_CURVE_POINT"] = "SIP_3006";
|
|
281
311
|
ErrorCode2["INVALID_SCALAR"] = "SIP_3007";
|
|
312
|
+
ErrorCode2["INVALID_KEY_SIZE"] = "SIP_3008";
|
|
313
|
+
ErrorCode2["INVALID_ENCRYPTED_DATA"] = "SIP_3009";
|
|
314
|
+
ErrorCode2["INVALID_COMMITMENT"] = "SIP_3010";
|
|
315
|
+
ErrorCode2["INVALID_TIME_LOCK"] = "SIP_3011";
|
|
316
|
+
ErrorCode2["INVALID_SHARE"] = "SIP_3012";
|
|
317
|
+
ErrorCode2["INVALID_THRESHOLD"] = "SIP_3013";
|
|
318
|
+
ErrorCode2["CRYPTO_OPERATION_FAILED"] = "SIP_3014";
|
|
319
|
+
ErrorCode2["INVALID_FORMAT"] = "SIP_3015";
|
|
282
320
|
ErrorCode2["PROOF_FAILED"] = "SIP_4000";
|
|
283
321
|
ErrorCode2["PROOF_GENERATION_FAILED"] = "SIP_4001";
|
|
284
322
|
ErrorCode2["PROOF_VERIFICATION_FAILED"] = "SIP_4002";
|
|
@@ -474,7 +512,16 @@ var VALID_CHAIN_IDS = [
|
|
|
474
512
|
"polygon",
|
|
475
513
|
"arbitrum",
|
|
476
514
|
"optimism",
|
|
477
|
-
"base"
|
|
515
|
+
"base",
|
|
516
|
+
"bitcoin",
|
|
517
|
+
"aptos",
|
|
518
|
+
"sui",
|
|
519
|
+
"cosmos",
|
|
520
|
+
"osmosis",
|
|
521
|
+
"injective",
|
|
522
|
+
"celestia",
|
|
523
|
+
"sei",
|
|
524
|
+
"dydx"
|
|
478
525
|
];
|
|
479
526
|
function isValidChainId(chain) {
|
|
480
527
|
return VALID_CHAIN_IDS.includes(chain);
|
|
@@ -671,6 +718,12 @@ function isValidNearAddressFormat(address) {
|
|
|
671
718
|
if (address.includes("..")) return false;
|
|
672
719
|
return true;
|
|
673
720
|
}
|
|
721
|
+
function isValidCosmosAddressFormat(address) {
|
|
722
|
+
if (typeof address !== "string") return false;
|
|
723
|
+
if (address.length < 39 || address.length > 90) return false;
|
|
724
|
+
const bech32Pattern = /^[a-z]+1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38,}$/;
|
|
725
|
+
return bech32Pattern.test(address);
|
|
726
|
+
}
|
|
674
727
|
function getChainAddressType(chain) {
|
|
675
728
|
switch (chain) {
|
|
676
729
|
case "ethereum":
|
|
@@ -685,6 +738,13 @@ function getChainAddressType(chain) {
|
|
|
685
738
|
return "near";
|
|
686
739
|
case "zcash":
|
|
687
740
|
return "zcash";
|
|
741
|
+
case "cosmos":
|
|
742
|
+
case "osmosis":
|
|
743
|
+
case "injective":
|
|
744
|
+
case "celestia":
|
|
745
|
+
case "sei":
|
|
746
|
+
case "dydx":
|
|
747
|
+
return "cosmos";
|
|
688
748
|
default:
|
|
689
749
|
return "unknown";
|
|
690
750
|
}
|
|
@@ -728,6 +788,15 @@ function validateAddressForChain(address, chain, field = "address") {
|
|
|
728
788
|
);
|
|
729
789
|
}
|
|
730
790
|
break;
|
|
791
|
+
case "cosmos":
|
|
792
|
+
if (!isValidCosmosAddressFormat(address)) {
|
|
793
|
+
throw new ValidationError(
|
|
794
|
+
`Invalid address format for ${chain}. Expected Cosmos bech32 address, got: ${address.slice(0, 20)}...`,
|
|
795
|
+
field,
|
|
796
|
+
{ chain, expectedFormat: "bech32" }
|
|
797
|
+
);
|
|
798
|
+
}
|
|
799
|
+
break;
|
|
731
800
|
default:
|
|
732
801
|
break;
|
|
733
802
|
}
|
|
@@ -779,7 +848,7 @@ function secureWipeAll(...buffers) {
|
|
|
779
848
|
function generateStealthMetaAddress(chain, label) {
|
|
780
849
|
if (!isValidChainId(chain)) {
|
|
781
850
|
throw new ValidationError(
|
|
782
|
-
`invalid chain '${chain}', must be one of: solana, ethereum, near, zcash, polygon, arbitrum, optimism, base`,
|
|
851
|
+
`invalid chain '${chain}', must be one of: solana, ethereum, near, zcash, polygon, arbitrum, optimism, base, bitcoin, aptos, sui, cosmos, osmosis, injective, celestia, sei, dydx`,
|
|
783
852
|
"chain"
|
|
784
853
|
);
|
|
785
854
|
}
|
|
@@ -1059,7 +1128,7 @@ function toChecksumAddress(address) {
|
|
|
1059
1128
|
return checksummed;
|
|
1060
1129
|
}
|
|
1061
1130
|
var ED25519_ORDER = 2n ** 252n + 27742317777372353535851937790883648493n;
|
|
1062
|
-
var ED25519_CHAINS = ["solana", "near"];
|
|
1131
|
+
var ED25519_CHAINS = ["solana", "near", "aptos", "sui"];
|
|
1063
1132
|
function isEd25519Chain(chain) {
|
|
1064
1133
|
return ED25519_CHAINS.includes(chain);
|
|
1065
1134
|
}
|
|
@@ -1144,7 +1213,7 @@ function bigIntToBytesLE(value, length) {
|
|
|
1144
1213
|
function generateEd25519StealthMetaAddress(chain, label) {
|
|
1145
1214
|
if (!isValidChainId(chain)) {
|
|
1146
1215
|
throw new ValidationError(
|
|
1147
|
-
`invalid chain '${chain}', must be one of: solana, ethereum, near, zcash, polygon, arbitrum, optimism, base`,
|
|
1216
|
+
`invalid chain '${chain}', must be one of: solana, ethereum, near, zcash, polygon, arbitrum, optimism, base, bitcoin, aptos, sui, cosmos, osmosis, injective, celestia, sei, dydx`,
|
|
1148
1217
|
"chain"
|
|
1149
1218
|
);
|
|
1150
1219
|
}
|
|
@@ -2514,7 +2583,15 @@ var CHAIN_BLOCKCHAIN_MAP = {
|
|
|
2514
2583
|
arbitrum: "evm",
|
|
2515
2584
|
optimism: "evm",
|
|
2516
2585
|
base: "evm",
|
|
2517
|
-
bitcoin: "bitcoin"
|
|
2586
|
+
bitcoin: "bitcoin",
|
|
2587
|
+
aptos: "aptos",
|
|
2588
|
+
sui: "sui",
|
|
2589
|
+
cosmos: "cosmos",
|
|
2590
|
+
osmosis: "cosmos",
|
|
2591
|
+
injective: "cosmos",
|
|
2592
|
+
celestia: "cosmos",
|
|
2593
|
+
sei: "cosmos",
|
|
2594
|
+
dydx: "cosmos"
|
|
2518
2595
|
};
|
|
2519
2596
|
var NEARIntentsAdapter = class {
|
|
2520
2597
|
client;
|
|
@@ -3274,6 +3351,448 @@ function createProductionSIP(config) {
|
|
|
3274
3351
|
});
|
|
3275
3352
|
}
|
|
3276
3353
|
|
|
3354
|
+
// src/move/aptos.ts
|
|
3355
|
+
var import_sha32 = require("@noble/hashes/sha3");
|
|
3356
|
+
var import_utils7 = require("@noble/hashes/utils");
|
|
3357
|
+
var APTOS_SINGLE_ED25519_SCHEME = 0;
|
|
3358
|
+
function ed25519PublicKeyToAptosAddress(publicKey) {
|
|
3359
|
+
if (!isValidHex(publicKey)) {
|
|
3360
|
+
throw new ValidationError(
|
|
3361
|
+
"publicKey must be a valid hex string with 0x prefix",
|
|
3362
|
+
"publicKey"
|
|
3363
|
+
);
|
|
3364
|
+
}
|
|
3365
|
+
if (!isValidEd25519PublicKey(publicKey)) {
|
|
3366
|
+
throw new ValidationError(
|
|
3367
|
+
"publicKey must be 32 bytes (64 hex characters)",
|
|
3368
|
+
"publicKey"
|
|
3369
|
+
);
|
|
3370
|
+
}
|
|
3371
|
+
const publicKeyBytes = (0, import_utils7.hexToBytes)(publicKey.slice(2));
|
|
3372
|
+
const authKeyInput = new Uint8Array(publicKeyBytes.length + 1);
|
|
3373
|
+
authKeyInput.set(publicKeyBytes, 0);
|
|
3374
|
+
authKeyInput[publicKeyBytes.length] = APTOS_SINGLE_ED25519_SCHEME;
|
|
3375
|
+
const addressHash = (0, import_sha32.sha3_256)(authKeyInput);
|
|
3376
|
+
return `0x${(0, import_utils7.bytesToHex)(addressHash)}`;
|
|
3377
|
+
}
|
|
3378
|
+
function isValidAptosAddress(address) {
|
|
3379
|
+
if (typeof address !== "string" || address.length === 0) {
|
|
3380
|
+
return false;
|
|
3381
|
+
}
|
|
3382
|
+
if (!address.startsWith("0x")) {
|
|
3383
|
+
return false;
|
|
3384
|
+
}
|
|
3385
|
+
const hexPart = address.slice(2);
|
|
3386
|
+
if (hexPart.length !== 64) {
|
|
3387
|
+
return false;
|
|
3388
|
+
}
|
|
3389
|
+
return /^[0-9a-fA-F]{64}$/.test(hexPart);
|
|
3390
|
+
}
|
|
3391
|
+
function aptosAddressToAuthKey(address) {
|
|
3392
|
+
if (!isValidAptosAddress(address)) {
|
|
3393
|
+
throw new ValidationError(
|
|
3394
|
+
"Invalid Aptos address format (must be 0x-prefixed 64 hex characters)",
|
|
3395
|
+
"address"
|
|
3396
|
+
);
|
|
3397
|
+
}
|
|
3398
|
+
return address.toLowerCase();
|
|
3399
|
+
}
|
|
3400
|
+
function generateAptosStealthAddress(recipientMetaAddress) {
|
|
3401
|
+
if (recipientMetaAddress.chain !== "aptos") {
|
|
3402
|
+
throw new ValidationError(
|
|
3403
|
+
`Expected chain 'aptos', got '${recipientMetaAddress.chain}'`,
|
|
3404
|
+
"recipientMetaAddress.chain"
|
|
3405
|
+
);
|
|
3406
|
+
}
|
|
3407
|
+
const { stealthAddress, sharedSecret } = generateEd25519StealthAddress(recipientMetaAddress);
|
|
3408
|
+
const aptosAddress = ed25519PublicKeyToAptosAddress(stealthAddress.address);
|
|
3409
|
+
return {
|
|
3410
|
+
stealthAddress: aptosAddress,
|
|
3411
|
+
stealthPublicKey: stealthAddress.address,
|
|
3412
|
+
ephemeralPublicKey: stealthAddress.ephemeralPublicKey,
|
|
3413
|
+
viewTag: stealthAddress.viewTag,
|
|
3414
|
+
sharedSecret
|
|
3415
|
+
};
|
|
3416
|
+
}
|
|
3417
|
+
function deriveAptosStealthPrivateKey(stealthAddress, spendingPrivateKey, viewingPrivateKey) {
|
|
3418
|
+
const recovery = deriveEd25519StealthPrivateKey(
|
|
3419
|
+
stealthAddress,
|
|
3420
|
+
spendingPrivateKey,
|
|
3421
|
+
viewingPrivateKey
|
|
3422
|
+
);
|
|
3423
|
+
const aptosAddress = ed25519PublicKeyToAptosAddress(recovery.stealthAddress);
|
|
3424
|
+
return {
|
|
3425
|
+
...recovery,
|
|
3426
|
+
aptosAddress
|
|
3427
|
+
};
|
|
3428
|
+
}
|
|
3429
|
+
function checkAptosStealthAddress(stealthAddress, spendingPrivateKey, viewingPrivateKey) {
|
|
3430
|
+
return checkEd25519StealthAddress(
|
|
3431
|
+
stealthAddress,
|
|
3432
|
+
spendingPrivateKey,
|
|
3433
|
+
viewingPrivateKey
|
|
3434
|
+
);
|
|
3435
|
+
}
|
|
3436
|
+
var AptosStealthService = class {
|
|
3437
|
+
/**
|
|
3438
|
+
* Generate a stealth address for an Aptos recipient
|
|
3439
|
+
*
|
|
3440
|
+
* @param recipientMetaAddress - Recipient's stealth meta-address
|
|
3441
|
+
* @returns Complete stealth address result
|
|
3442
|
+
*/
|
|
3443
|
+
generateStealthAddress(recipientMetaAddress) {
|
|
3444
|
+
return generateAptosStealthAddress(recipientMetaAddress);
|
|
3445
|
+
}
|
|
3446
|
+
/**
|
|
3447
|
+
* Convert an ed25519 public key to Aptos address format
|
|
3448
|
+
*
|
|
3449
|
+
* @param publicKey - 32-byte ed25519 public key
|
|
3450
|
+
* @returns Aptos address string
|
|
3451
|
+
*/
|
|
3452
|
+
stealthKeyToAptosAddress(publicKey) {
|
|
3453
|
+
return ed25519PublicKeyToAptosAddress(publicKey);
|
|
3454
|
+
}
|
|
3455
|
+
/**
|
|
3456
|
+
* Derive the private key for a stealth address
|
|
3457
|
+
*
|
|
3458
|
+
* @param stealthAddress - Stealth address data
|
|
3459
|
+
* @param spendingPrivateKey - Recipient's spending private key
|
|
3460
|
+
* @param viewingPrivateKey - Recipient's viewing private key
|
|
3461
|
+
* @returns Recovery data with derived private key
|
|
3462
|
+
*/
|
|
3463
|
+
deriveStealthPrivateKey(stealthAddress, spendingPrivateKey, viewingPrivateKey) {
|
|
3464
|
+
return deriveAptosStealthPrivateKey(stealthAddress, spendingPrivateKey, viewingPrivateKey);
|
|
3465
|
+
}
|
|
3466
|
+
/**
|
|
3467
|
+
* Check if a stealth address belongs to this recipient
|
|
3468
|
+
*
|
|
3469
|
+
* @param stealthAddress - Stealth address to check
|
|
3470
|
+
* @param spendingPrivateKey - Recipient's spending private key
|
|
3471
|
+
* @param viewingPrivateKey - Recipient's viewing private key
|
|
3472
|
+
* @returns true if the address belongs to this recipient
|
|
3473
|
+
*/
|
|
3474
|
+
checkStealthAddress(stealthAddress, spendingPrivateKey, viewingPrivateKey) {
|
|
3475
|
+
return checkAptosStealthAddress(stealthAddress, spendingPrivateKey, viewingPrivateKey);
|
|
3476
|
+
}
|
|
3477
|
+
/**
|
|
3478
|
+
* Validate an Aptos address format
|
|
3479
|
+
*
|
|
3480
|
+
* @param address - Address to validate
|
|
3481
|
+
* @returns true if valid format
|
|
3482
|
+
*/
|
|
3483
|
+
isValidAddress(address) {
|
|
3484
|
+
return isValidAptosAddress(address);
|
|
3485
|
+
}
|
|
3486
|
+
};
|
|
3487
|
+
|
|
3488
|
+
// src/move/sui.ts
|
|
3489
|
+
var import_blake2b = require("@noble/hashes/blake2b");
|
|
3490
|
+
var import_utils8 = require("@noble/hashes/utils");
|
|
3491
|
+
|
|
3492
|
+
// src/cosmos/stealth.ts
|
|
3493
|
+
var import_sha2566 = require("@noble/hashes/sha256");
|
|
3494
|
+
var import_ripemd160 = require("@noble/hashes/ripemd160");
|
|
3495
|
+
var import_utils9 = require("@noble/hashes/utils");
|
|
3496
|
+
var import_base = require("@scure/base");
|
|
3497
|
+
var CHAIN_PREFIXES = {
|
|
3498
|
+
cosmos: "cosmos",
|
|
3499
|
+
osmosis: "osmo",
|
|
3500
|
+
injective: "inj",
|
|
3501
|
+
celestia: "celestia",
|
|
3502
|
+
sei: "sei",
|
|
3503
|
+
dydx: "dydx"
|
|
3504
|
+
};
|
|
3505
|
+
var CosmosStealthService = class {
|
|
3506
|
+
/**
|
|
3507
|
+
* Generate a stealth meta-address for a Cosmos chain
|
|
3508
|
+
*
|
|
3509
|
+
* @param chain - Cosmos chain identifier
|
|
3510
|
+
* @param label - Optional human-readable label
|
|
3511
|
+
* @returns Stealth meta-address and private keys
|
|
3512
|
+
* @throws {ValidationError} If chain is invalid
|
|
3513
|
+
*
|
|
3514
|
+
* @example
|
|
3515
|
+
* ```typescript
|
|
3516
|
+
* const service = new CosmosStealthService()
|
|
3517
|
+
* const { metaAddress, spendingPrivateKey, viewingPrivateKey } =
|
|
3518
|
+
* service.generateStealthMetaAddress('cosmos', 'My Cosmos Wallet')
|
|
3519
|
+
* ```
|
|
3520
|
+
*/
|
|
3521
|
+
generateStealthMetaAddress(chain, label) {
|
|
3522
|
+
if (!this.isValidCosmosChain(chain)) {
|
|
3523
|
+
throw new ValidationError(
|
|
3524
|
+
`invalid Cosmos chain '${chain}', must be one of: ${Object.keys(CHAIN_PREFIXES).join(", ")}`,
|
|
3525
|
+
"chain"
|
|
3526
|
+
);
|
|
3527
|
+
}
|
|
3528
|
+
const result = generateStealthMetaAddress("ethereum", label);
|
|
3529
|
+
return {
|
|
3530
|
+
...result,
|
|
3531
|
+
metaAddress: {
|
|
3532
|
+
...result.metaAddress,
|
|
3533
|
+
chain
|
|
3534
|
+
// Will be updated in types package
|
|
3535
|
+
}
|
|
3536
|
+
};
|
|
3537
|
+
}
|
|
3538
|
+
/**
|
|
3539
|
+
* Generate a one-time stealth address for a Cosmos chain
|
|
3540
|
+
*
|
|
3541
|
+
* @param spendingPubKey - Recipient's spending public key (33-byte compressed)
|
|
3542
|
+
* @param viewingPubKey - Recipient's viewing public key (33-byte compressed)
|
|
3543
|
+
* @param chain - Cosmos chain identifier
|
|
3544
|
+
* @returns Cosmos stealth address with bech32 encoding
|
|
3545
|
+
* @throws {ValidationError} If keys or chain are invalid
|
|
3546
|
+
*
|
|
3547
|
+
* @example
|
|
3548
|
+
* ```typescript
|
|
3549
|
+
* const service = new CosmosStealthService()
|
|
3550
|
+
* const result = service.generateStealthAddress(
|
|
3551
|
+
* spendingKey,
|
|
3552
|
+
* viewingKey,
|
|
3553
|
+
* 'osmosis'
|
|
3554
|
+
* )
|
|
3555
|
+
* console.log(result.stealthAddress) // "osmo1..."
|
|
3556
|
+
* ```
|
|
3557
|
+
*/
|
|
3558
|
+
generateStealthAddress(spendingPubKey, viewingPubKey, chain) {
|
|
3559
|
+
if (!this.isValidCosmosChain(chain)) {
|
|
3560
|
+
throw new ValidationError(
|
|
3561
|
+
`invalid Cosmos chain '${chain}', must be one of: ${Object.keys(CHAIN_PREFIXES).join(", ")}`,
|
|
3562
|
+
"chain"
|
|
3563
|
+
);
|
|
3564
|
+
}
|
|
3565
|
+
if (spendingPubKey.length !== 33) {
|
|
3566
|
+
throw new ValidationError(
|
|
3567
|
+
"spendingPubKey must be 33 bytes (compressed secp256k1)",
|
|
3568
|
+
"spendingPubKey"
|
|
3569
|
+
);
|
|
3570
|
+
}
|
|
3571
|
+
if (viewingPubKey.length !== 33) {
|
|
3572
|
+
throw new ValidationError(
|
|
3573
|
+
"viewingPubKey must be 33 bytes (compressed secp256k1)",
|
|
3574
|
+
"viewingPubKey"
|
|
3575
|
+
);
|
|
3576
|
+
}
|
|
3577
|
+
const metaAddress = {
|
|
3578
|
+
spendingKey: `0x${(0, import_utils9.bytesToHex)(spendingPubKey)}`,
|
|
3579
|
+
viewingKey: `0x${(0, import_utils9.bytesToHex)(viewingPubKey)}`,
|
|
3580
|
+
chain: "ethereum"
|
|
3581
|
+
// Use ethereum for secp256k1 generation
|
|
3582
|
+
};
|
|
3583
|
+
const { stealthAddress, sharedSecret } = generateStealthAddress(metaAddress);
|
|
3584
|
+
const cosmosAddress = this.stealthKeyToCosmosAddress(
|
|
3585
|
+
(0, import_utils9.hexToBytes)(stealthAddress.address.slice(2)),
|
|
3586
|
+
CHAIN_PREFIXES[chain]
|
|
3587
|
+
);
|
|
3588
|
+
return {
|
|
3589
|
+
stealthAddress: cosmosAddress,
|
|
3590
|
+
stealthPublicKey: stealthAddress.address,
|
|
3591
|
+
ephemeralPublicKey: stealthAddress.ephemeralPublicKey,
|
|
3592
|
+
viewTag: stealthAddress.viewTag,
|
|
3593
|
+
viewKeyHash: sharedSecret
|
|
3594
|
+
};
|
|
3595
|
+
}
|
|
3596
|
+
/**
|
|
3597
|
+
* Generate stealth address from StealthMetaAddress
|
|
3598
|
+
*
|
|
3599
|
+
* Convenience method that accepts a StealthMetaAddress directly.
|
|
3600
|
+
*
|
|
3601
|
+
* @param recipientMetaAddress - Recipient's stealth meta-address
|
|
3602
|
+
* @param chain - Cosmos chain identifier
|
|
3603
|
+
* @returns Cosmos stealth address with bech32 encoding
|
|
3604
|
+
* @throws {ValidationError} If meta-address or chain are invalid
|
|
3605
|
+
*
|
|
3606
|
+
* @example
|
|
3607
|
+
* ```typescript
|
|
3608
|
+
* const service = new CosmosStealthService()
|
|
3609
|
+
* const result = service.generateStealthAddressFromMeta(metaAddress, 'cosmos')
|
|
3610
|
+
* ```
|
|
3611
|
+
*/
|
|
3612
|
+
generateStealthAddressFromMeta(recipientMetaAddress, chain) {
|
|
3613
|
+
const spendingPubKey = (0, import_utils9.hexToBytes)(recipientMetaAddress.spendingKey.slice(2));
|
|
3614
|
+
const viewingPubKey = (0, import_utils9.hexToBytes)(recipientMetaAddress.viewingKey.slice(2));
|
|
3615
|
+
return this.generateStealthAddress(spendingPubKey, viewingPubKey, chain);
|
|
3616
|
+
}
|
|
3617
|
+
/**
|
|
3618
|
+
* Convert stealth public key to Cosmos bech32 address
|
|
3619
|
+
*
|
|
3620
|
+
* Algorithm:
|
|
3621
|
+
* 1. SHA256 hash of compressed public key
|
|
3622
|
+
* 2. RIPEMD160 hash of SHA256 hash
|
|
3623
|
+
* 3. Bech32 encode with chain prefix
|
|
3624
|
+
*
|
|
3625
|
+
* @param publicKey - Compressed secp256k1 public key (33 bytes)
|
|
3626
|
+
* @param prefix - Bech32 address prefix (e.g., "cosmos", "osmo")
|
|
3627
|
+
* @returns Bech32-encoded address
|
|
3628
|
+
* @throws {ValidationError} If public key is invalid
|
|
3629
|
+
*
|
|
3630
|
+
* @example
|
|
3631
|
+
* ```typescript
|
|
3632
|
+
* const service = new CosmosStealthService()
|
|
3633
|
+
* const address = service.stealthKeyToCosmosAddress(pubKey, 'cosmos')
|
|
3634
|
+
* // Returns: "cosmos1abc..."
|
|
3635
|
+
* ```
|
|
3636
|
+
*/
|
|
3637
|
+
stealthKeyToCosmosAddress(publicKey, prefix) {
|
|
3638
|
+
if (publicKey.length !== 33) {
|
|
3639
|
+
throw new ValidationError(
|
|
3640
|
+
"public key must be 33 bytes (compressed secp256k1)",
|
|
3641
|
+
"publicKey"
|
|
3642
|
+
);
|
|
3643
|
+
}
|
|
3644
|
+
const sha256Hash = (0, import_sha2566.sha256)(publicKey);
|
|
3645
|
+
const hash160 = (0, import_ripemd160.ripemd160)(sha256Hash);
|
|
3646
|
+
const words = import_base.bech32.toWords(hash160);
|
|
3647
|
+
return import_base.bech32.encode(prefix, words);
|
|
3648
|
+
}
|
|
3649
|
+
/**
|
|
3650
|
+
* Derive stealth private key for recipient to claim funds
|
|
3651
|
+
*
|
|
3652
|
+
* @param stealthAddress - The stealth address to recover (as StealthAddress)
|
|
3653
|
+
* @param spendingPrivateKey - Recipient's spending private key
|
|
3654
|
+
* @param viewingPrivateKey - Recipient's viewing private key
|
|
3655
|
+
* @returns Recovery data with derived private key
|
|
3656
|
+
* @throws {ValidationError} If any input is invalid
|
|
3657
|
+
*
|
|
3658
|
+
* @example
|
|
3659
|
+
* ```typescript
|
|
3660
|
+
* const service = new CosmosStealthService()
|
|
3661
|
+
* const recovery = service.deriveStealthPrivateKey(
|
|
3662
|
+
* stealthAddress,
|
|
3663
|
+
* spendingPrivKey,
|
|
3664
|
+
* viewingPrivKey
|
|
3665
|
+
* )
|
|
3666
|
+
* // Use recovery.privateKey to spend funds
|
|
3667
|
+
* ```
|
|
3668
|
+
*/
|
|
3669
|
+
deriveStealthPrivateKey(stealthAddress, spendingPrivateKey, viewingPrivateKey) {
|
|
3670
|
+
return deriveStealthPrivateKey(
|
|
3671
|
+
stealthAddress,
|
|
3672
|
+
spendingPrivateKey,
|
|
3673
|
+
viewingPrivateKey
|
|
3674
|
+
);
|
|
3675
|
+
}
|
|
3676
|
+
/**
|
|
3677
|
+
* Check if a string is a valid Cosmos chain identifier
|
|
3678
|
+
*/
|
|
3679
|
+
isValidCosmosChain(chain) {
|
|
3680
|
+
return chain in CHAIN_PREFIXES;
|
|
3681
|
+
}
|
|
3682
|
+
/**
|
|
3683
|
+
* Decode a Cosmos bech32 address to raw hash
|
|
3684
|
+
*
|
|
3685
|
+
* @param address - Bech32-encoded address
|
|
3686
|
+
* @returns Decoded address hash (20 bytes)
|
|
3687
|
+
* @throws {ValidationError} If address is invalid
|
|
3688
|
+
*
|
|
3689
|
+
* @example
|
|
3690
|
+
* ```typescript
|
|
3691
|
+
* const service = new CosmosStealthService()
|
|
3692
|
+
* const { prefix, hash } = service.decodeBech32Address('cosmos1abc...')
|
|
3693
|
+
* ```
|
|
3694
|
+
*/
|
|
3695
|
+
decodeBech32Address(address) {
|
|
3696
|
+
try {
|
|
3697
|
+
const decoded = import_base.bech32.decode(address);
|
|
3698
|
+
const hash2 = import_base.bech32.fromWords(decoded.words);
|
|
3699
|
+
if (hash2.length !== 20) {
|
|
3700
|
+
throw new ValidationError(
|
|
3701
|
+
`invalid address hash length: ${hash2.length}, expected 20`,
|
|
3702
|
+
"address"
|
|
3703
|
+
);
|
|
3704
|
+
}
|
|
3705
|
+
return {
|
|
3706
|
+
prefix: decoded.prefix,
|
|
3707
|
+
hash: new Uint8Array(hash2)
|
|
3708
|
+
};
|
|
3709
|
+
} catch (error) {
|
|
3710
|
+
if (error instanceof ValidationError) {
|
|
3711
|
+
throw error;
|
|
3712
|
+
}
|
|
3713
|
+
throw new ValidationError(
|
|
3714
|
+
`invalid bech32 address: ${error instanceof Error ? error.message : "unknown error"}`,
|
|
3715
|
+
"address"
|
|
3716
|
+
);
|
|
3717
|
+
}
|
|
3718
|
+
}
|
|
3719
|
+
/**
|
|
3720
|
+
* Validate a Cosmos bech32 address format
|
|
3721
|
+
*
|
|
3722
|
+
* @param address - Address to validate
|
|
3723
|
+
* @param expectedChain - Optional chain to validate prefix against
|
|
3724
|
+
* @returns true if valid, false otherwise
|
|
3725
|
+
*
|
|
3726
|
+
* @example
|
|
3727
|
+
* ```typescript
|
|
3728
|
+
* const service = new CosmosStealthService()
|
|
3729
|
+
* service.isValidCosmosAddress('cosmos1abc...', 'cosmos') // true
|
|
3730
|
+
* service.isValidCosmosAddress('osmo1xyz...', 'cosmos') // false (wrong prefix)
|
|
3731
|
+
* ```
|
|
3732
|
+
*/
|
|
3733
|
+
isValidCosmosAddress(address, expectedChain) {
|
|
3734
|
+
try {
|
|
3735
|
+
const { prefix, hash: hash2 } = this.decodeBech32Address(address);
|
|
3736
|
+
if (hash2.length !== 20) {
|
|
3737
|
+
return false;
|
|
3738
|
+
}
|
|
3739
|
+
if (expectedChain) {
|
|
3740
|
+
return prefix === CHAIN_PREFIXES[expectedChain];
|
|
3741
|
+
}
|
|
3742
|
+
return Object.values(CHAIN_PREFIXES).includes(prefix);
|
|
3743
|
+
} catch {
|
|
3744
|
+
return false;
|
|
3745
|
+
}
|
|
3746
|
+
}
|
|
3747
|
+
/**
|
|
3748
|
+
* Get the chain ID from a bech32 address prefix
|
|
3749
|
+
*
|
|
3750
|
+
* @param address - Bech32-encoded address
|
|
3751
|
+
* @returns Chain ID or null if unknown prefix
|
|
3752
|
+
*
|
|
3753
|
+
* @example
|
|
3754
|
+
* ```typescript
|
|
3755
|
+
* const service = new CosmosStealthService()
|
|
3756
|
+
* service.getChainFromAddress('cosmos1abc...') // 'cosmos'
|
|
3757
|
+
* service.getChainFromAddress('osmo1xyz...') // 'osmosis'
|
|
3758
|
+
* ```
|
|
3759
|
+
*/
|
|
3760
|
+
getChainFromAddress(address) {
|
|
3761
|
+
try {
|
|
3762
|
+
const { prefix } = this.decodeBech32Address(address);
|
|
3763
|
+
for (const [chain, chainPrefix] of Object.entries(CHAIN_PREFIXES)) {
|
|
3764
|
+
if (chainPrefix === prefix) {
|
|
3765
|
+
return chain;
|
|
3766
|
+
}
|
|
3767
|
+
}
|
|
3768
|
+
return null;
|
|
3769
|
+
} catch {
|
|
3770
|
+
return null;
|
|
3771
|
+
}
|
|
3772
|
+
}
|
|
3773
|
+
};
|
|
3774
|
+
function generateCosmosStealthMetaAddress(chain, label) {
|
|
3775
|
+
const service = new CosmosStealthService();
|
|
3776
|
+
return service.generateStealthMetaAddress(chain, label);
|
|
3777
|
+
}
|
|
3778
|
+
function generateCosmosStealthAddress(spendingPubKey, viewingPubKey, chain) {
|
|
3779
|
+
const service = new CosmosStealthService();
|
|
3780
|
+
return service.generateStealthAddress(spendingPubKey, viewingPubKey, chain);
|
|
3781
|
+
}
|
|
3782
|
+
function stealthKeyToCosmosAddress(publicKey, prefix) {
|
|
3783
|
+
const service = new CosmosStealthService();
|
|
3784
|
+
return service.stealthKeyToCosmosAddress(publicKey, prefix);
|
|
3785
|
+
}
|
|
3786
|
+
function isValidCosmosAddress(address, expectedChain) {
|
|
3787
|
+
const service = new CosmosStealthService();
|
|
3788
|
+
return service.isValidCosmosAddress(address, expectedChain);
|
|
3789
|
+
}
|
|
3790
|
+
|
|
3791
|
+
// src/cosmos/ibc-stealth.ts
|
|
3792
|
+
var import_utils10 = require("@noble/hashes/utils");
|
|
3793
|
+
var import_secp256k13 = require("@noble/curves/secp256k1");
|
|
3794
|
+
var import_sha2567 = require("@noble/hashes/sha256");
|
|
3795
|
+
|
|
3277
3796
|
// src/proofs/interface.ts
|
|
3278
3797
|
var ProofGenerationError = class extends Error {
|
|
3279
3798
|
proofType;
|
|
@@ -3287,8 +3806,8 @@ var ProofGenerationError = class extends Error {
|
|
|
3287
3806
|
};
|
|
3288
3807
|
|
|
3289
3808
|
// src/proofs/mock.ts
|
|
3290
|
-
var
|
|
3291
|
-
var
|
|
3809
|
+
var import_sha2568 = require("@noble/hashes/sha256");
|
|
3810
|
+
var import_utils11 = require("@noble/hashes/utils");
|
|
3292
3811
|
var MOCK_PROOF_PREFIX = "0x4d4f434b";
|
|
3293
3812
|
var WARNING_MESSAGE = `
|
|
3294
3813
|
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
@@ -3453,22 +3972,22 @@ var MockProofProvider = class {
|
|
|
3453
3972
|
{ type: proofType, params },
|
|
3454
3973
|
(_, v) => typeof v === "bigint" ? v.toString() : v
|
|
3455
3974
|
);
|
|
3456
|
-
const hash2 = (0,
|
|
3457
|
-
const random = (0,
|
|
3975
|
+
const hash2 = (0, import_sha2568.sha256)(new TextEncoder().encode(input));
|
|
3976
|
+
const random = (0, import_utils11.randomBytes)(16);
|
|
3458
3977
|
const combined = new Uint8Array(4 + hash2.length + random.length);
|
|
3459
3978
|
combined.set(new TextEncoder().encode("MOCK"), 0);
|
|
3460
3979
|
combined.set(hash2, 4);
|
|
3461
3980
|
combined.set(random, 4 + hash2.length);
|
|
3462
|
-
return `${MOCK_PROOF_PREFIX}${(0,
|
|
3981
|
+
return `${MOCK_PROOF_PREFIX}${(0, import_utils11.bytesToHex)(combined.slice(4))}`;
|
|
3463
3982
|
}
|
|
3464
3983
|
hashToHex(data) {
|
|
3465
|
-
const hash2 = (0,
|
|
3466
|
-
return `0x${(0,
|
|
3984
|
+
const hash2 = (0, import_sha2568.sha256)(new TextEncoder().encode(data));
|
|
3985
|
+
return `0x${(0, import_utils11.bytesToHex)(hash2)}`;
|
|
3467
3986
|
}
|
|
3468
3987
|
};
|
|
3469
3988
|
|
|
3470
3989
|
// src/proofs/browser-utils.ts
|
|
3471
|
-
function
|
|
3990
|
+
function hexToBytes9(hex) {
|
|
3472
3991
|
const h = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
3473
3992
|
if (h.length === 0) return new Uint8Array(0);
|
|
3474
3993
|
if (h.length % 2 !== 0) {
|
|
@@ -3480,7 +3999,7 @@ function hexToBytes5(hex) {
|
|
|
3480
3999
|
}
|
|
3481
4000
|
return bytes;
|
|
3482
4001
|
}
|
|
3483
|
-
function
|
|
4002
|
+
function bytesToHex11(bytes) {
|
|
3484
4003
|
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
3485
4004
|
}
|
|
3486
4005
|
function isBrowser() {
|
|
@@ -3522,18 +4041,34 @@ var CHAIN_NUMERIC_IDS = {
|
|
|
3522
4041
|
// Non-standard, SIP-specific
|
|
3523
4042
|
near: 502,
|
|
3524
4043
|
// Non-standard, SIP-specific
|
|
3525
|
-
zcash: 503
|
|
4044
|
+
zcash: 503,
|
|
4045
|
+
// Non-standard, SIP-specific
|
|
4046
|
+
aptos: 504,
|
|
4047
|
+
// Non-standard, SIP-specific
|
|
4048
|
+
sui: 505,
|
|
4049
|
+
// Non-standard, SIP-specific
|
|
4050
|
+
cosmos: 506,
|
|
4051
|
+
// Non-standard, SIP-specific (Cosmos Hub)
|
|
4052
|
+
osmosis: 507,
|
|
4053
|
+
// Non-standard, SIP-specific
|
|
4054
|
+
injective: 508,
|
|
4055
|
+
// Non-standard, SIP-specific
|
|
4056
|
+
celestia: 509,
|
|
4057
|
+
// Non-standard, SIP-specific
|
|
4058
|
+
sei: 510,
|
|
4059
|
+
// Non-standard, SIP-specific
|
|
4060
|
+
dydx: 511
|
|
3526
4061
|
// Non-standard, SIP-specific
|
|
3527
4062
|
};
|
|
3528
4063
|
|
|
3529
4064
|
// src/oracle/verification.ts
|
|
3530
4065
|
var import_ed255192 = require("@noble/curves/ed25519");
|
|
3531
|
-
var
|
|
3532
|
-
var
|
|
4066
|
+
var import_sha25610 = require("@noble/hashes/sha256");
|
|
4067
|
+
var import_utils13 = require("@noble/hashes/utils");
|
|
3533
4068
|
|
|
3534
4069
|
// src/oracle/serialization.ts
|
|
3535
|
-
var
|
|
3536
|
-
var
|
|
4070
|
+
var import_sha2569 = require("@noble/hashes/sha256");
|
|
4071
|
+
var import_utils12 = require("@noble/hashes/utils");
|
|
3537
4072
|
function serializeAttestationMessage(message) {
|
|
3538
4073
|
const buffer = new Uint8Array(197);
|
|
3539
4074
|
const view = new DataView(buffer.buffer);
|
|
@@ -3576,19 +4111,19 @@ function deserializeAttestationMessage(bytes) {
|
|
|
3576
4111
|
const version = bytes[offset++];
|
|
3577
4112
|
const chainId = view.getUint32(offset, false);
|
|
3578
4113
|
offset += 4;
|
|
3579
|
-
const intentHash = `0x${(0,
|
|
4114
|
+
const intentHash = `0x${(0, import_utils12.bytesToHex)(bytes.slice(offset, offset + 32))}`;
|
|
3580
4115
|
offset += 32;
|
|
3581
|
-
const recipient = `0x${(0,
|
|
4116
|
+
const recipient = `0x${(0, import_utils12.bytesToHex)(bytes.slice(offset, offset + 32))}`;
|
|
3582
4117
|
offset += 32;
|
|
3583
4118
|
const amount = bytesToBigint(bytes.slice(offset, offset + 16));
|
|
3584
4119
|
offset += 16;
|
|
3585
|
-
const assetId = `0x${(0,
|
|
4120
|
+
const assetId = `0x${(0, import_utils12.bytesToHex)(bytes.slice(offset, offset + 32))}`;
|
|
3586
4121
|
offset += 32;
|
|
3587
|
-
const txHash = `0x${(0,
|
|
4122
|
+
const txHash = `0x${(0, import_utils12.bytesToHex)(bytes.slice(offset, offset + 32))}`;
|
|
3588
4123
|
offset += 32;
|
|
3589
4124
|
const blockNumber = view.getBigUint64(offset, false);
|
|
3590
4125
|
offset += 8;
|
|
3591
|
-
const blockHash = `0x${(0,
|
|
4126
|
+
const blockHash = `0x${(0, import_utils12.bytesToHex)(bytes.slice(offset, offset + 32))}`;
|
|
3592
4127
|
offset += 32;
|
|
3593
4128
|
const timestamp = Number(view.getBigUint64(offset, false));
|
|
3594
4129
|
return {
|
|
@@ -3605,12 +4140,12 @@ function deserializeAttestationMessage(bytes) {
|
|
|
3605
4140
|
};
|
|
3606
4141
|
}
|
|
3607
4142
|
function computeAttestationHash(message) {
|
|
3608
|
-
const domain = (0,
|
|
4143
|
+
const domain = (0, import_utils12.utf8ToBytes)(ORACLE_DOMAIN);
|
|
3609
4144
|
const messageBytes = serializeAttestationMessage(message);
|
|
3610
4145
|
const toHash = new Uint8Array(domain.length + messageBytes.length);
|
|
3611
4146
|
toHash.set(domain, 0);
|
|
3612
4147
|
toHash.set(messageBytes, domain.length);
|
|
3613
|
-
return (0,
|
|
4148
|
+
return (0, import_sha2569.sha256)(toHash);
|
|
3614
4149
|
}
|
|
3615
4150
|
function getChainNumericId(chain) {
|
|
3616
4151
|
const id = CHAIN_NUMERIC_IDS[chain];
|
|
@@ -3621,7 +4156,7 @@ function getChainNumericId(chain) {
|
|
|
3621
4156
|
}
|
|
3622
4157
|
function normalizeToBytes(hex, length, field) {
|
|
3623
4158
|
const stripped = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
3624
|
-
const bytes = (0,
|
|
4159
|
+
const bytes = (0, import_utils12.hexToBytes)(stripped);
|
|
3625
4160
|
if (bytes.length === length) {
|
|
3626
4161
|
return bytes;
|
|
3627
4162
|
}
|
|
@@ -3654,9 +4189,9 @@ function bytesToBigint(bytes) {
|
|
|
3654
4189
|
|
|
3655
4190
|
// src/oracle/verification.ts
|
|
3656
4191
|
function deriveOracleId(publicKey) {
|
|
3657
|
-
const keyBytes = typeof publicKey === "string" ? (0,
|
|
3658
|
-
const hash2 = (0,
|
|
3659
|
-
return `0x${(0,
|
|
4192
|
+
const keyBytes = typeof publicKey === "string" ? (0, import_utils13.hexToBytes)(publicKey.startsWith("0x") ? publicKey.slice(2) : publicKey) : publicKey;
|
|
4193
|
+
const hash2 = (0, import_sha25610.sha256)(keyBytes);
|
|
4194
|
+
return `0x${(0, import_utils13.bytesToHex)(hash2)}`;
|
|
3660
4195
|
}
|
|
3661
4196
|
function verifyAttestation(attestation, registry) {
|
|
3662
4197
|
const { message, signatures } = attestation;
|
|
@@ -3686,10 +4221,10 @@ function verifyAttestation(attestation, registry) {
|
|
|
3686
4221
|
continue;
|
|
3687
4222
|
}
|
|
3688
4223
|
try {
|
|
3689
|
-
const publicKeyBytes = (0,
|
|
4224
|
+
const publicKeyBytes = (0, import_utils13.hexToBytes)(
|
|
3690
4225
|
oracle.publicKey.startsWith("0x") ? oracle.publicKey.slice(2) : oracle.publicKey
|
|
3691
4226
|
);
|
|
3692
|
-
const signatureBytes = (0,
|
|
4227
|
+
const signatureBytes = (0, import_utils13.hexToBytes)(
|
|
3693
4228
|
sig.signature.startsWith("0x") ? sig.signature.slice(2) : sig.signature
|
|
3694
4229
|
);
|
|
3695
4230
|
const isValid = import_ed255192.ed25519.verify(signatureBytes, messageHash, publicKeyBytes);
|
|
@@ -3714,10 +4249,10 @@ function verifyAttestation(attestation, registry) {
|
|
|
3714
4249
|
}
|
|
3715
4250
|
function verifyOracleSignature(signature, messageHash, oracle) {
|
|
3716
4251
|
try {
|
|
3717
|
-
const publicKeyBytes = (0,
|
|
4252
|
+
const publicKeyBytes = (0, import_utils13.hexToBytes)(
|
|
3718
4253
|
oracle.publicKey.startsWith("0x") ? oracle.publicKey.slice(2) : oracle.publicKey
|
|
3719
4254
|
);
|
|
3720
|
-
const signatureBytes = (0,
|
|
4255
|
+
const signatureBytes = (0, import_utils13.hexToBytes)(
|
|
3721
4256
|
signature.signature.startsWith("0x") ? signature.signature.slice(2) : signature.signature
|
|
3722
4257
|
);
|
|
3723
4258
|
return import_ed255192.ed25519.verify(signatureBytes, messageHash, publicKeyBytes);
|
|
@@ -3731,7 +4266,7 @@ function signAttestationMessage(messageHash, privateKey) {
|
|
|
3731
4266
|
const oracleId = deriveOracleId(publicKey);
|
|
3732
4267
|
return {
|
|
3733
4268
|
oracleId,
|
|
3734
|
-
signature: `0x${(0,
|
|
4269
|
+
signature: `0x${(0, import_utils13.bytesToHex)(signature)}`
|
|
3735
4270
|
};
|
|
3736
4271
|
}
|
|
3737
4272
|
function createOracleRegistry(config = {}) {
|
|
@@ -3783,14 +4318,14 @@ function hasEnoughOracles(registry) {
|
|
|
3783
4318
|
}
|
|
3784
4319
|
|
|
3785
4320
|
// src/index.ts
|
|
3786
|
-
var
|
|
3787
|
-
var
|
|
3788
|
-
var
|
|
3789
|
-
var
|
|
4321
|
+
var import_types55 = require("@sip-protocol/types");
|
|
4322
|
+
var import_types56 = require("@sip-protocol/types");
|
|
4323
|
+
var import_types57 = require("@sip-protocol/types");
|
|
4324
|
+
var import_types58 = require("@sip-protocol/types");
|
|
3790
4325
|
|
|
3791
4326
|
// src/solver/mock-solver.ts
|
|
3792
4327
|
var import_types7 = require("@sip-protocol/types");
|
|
3793
|
-
var
|
|
4328
|
+
var import_utils14 = require("@noble/hashes/utils");
|
|
3794
4329
|
var MockSolver = class {
|
|
3795
4330
|
info;
|
|
3796
4331
|
capabilities;
|
|
@@ -3872,7 +4407,7 @@ var MockSolver = class {
|
|
|
3872
4407
|
const spreadAmount = baseOutput * BigInt(Math.floor(this.spreadPercent * 1e4)) / 10000n;
|
|
3873
4408
|
const outputAmount = baseOutput + spreadAmount;
|
|
3874
4409
|
const feeAmount = outputAmount * BigInt(Math.floor(this.feePercent * 1e4)) / 10000n;
|
|
3875
|
-
const quoteId = `quote-${(0,
|
|
4410
|
+
const quoteId = `quote-${(0, import_utils14.bytesToHex)((0, import_utils14.randomBytes)(8))}`;
|
|
3876
4411
|
const now = Math.floor(Date.now() / 1e3);
|
|
3877
4412
|
const quote = {
|
|
3878
4413
|
quoteId,
|
|
@@ -3883,7 +4418,7 @@ var MockSolver = class {
|
|
|
3883
4418
|
expiry: now + 60,
|
|
3884
4419
|
// Quote valid for 1 minute
|
|
3885
4420
|
fee: feeAmount,
|
|
3886
|
-
signature: `0x${(0,
|
|
4421
|
+
signature: `0x${(0, import_utils14.bytesToHex)((0, import_utils14.randomBytes)(64))}`,
|
|
3887
4422
|
// Mock signature
|
|
3888
4423
|
validUntil: now + 60,
|
|
3889
4424
|
estimatedGas: 200000n
|
|
@@ -3920,7 +4455,7 @@ var MockSolver = class {
|
|
|
3920
4455
|
error: status.error
|
|
3921
4456
|
};
|
|
3922
4457
|
}
|
|
3923
|
-
const txHash = `0x${(0,
|
|
4458
|
+
const txHash = `0x${(0, import_utils14.bytesToHex)((0, import_utils14.randomBytes)(32))}`;
|
|
3924
4459
|
status.status = "completed";
|
|
3925
4460
|
status.txHash = txHash;
|
|
3926
4461
|
return {
|
|
@@ -3930,10 +4465,10 @@ var MockSolver = class {
|
|
|
3930
4465
|
txHash: intent.privacyLevel === "transparent" ? txHash : void 0,
|
|
3931
4466
|
fulfillmentProof: {
|
|
3932
4467
|
type: "fulfillment",
|
|
3933
|
-
proof: `0x${(0,
|
|
4468
|
+
proof: `0x${(0, import_utils14.bytesToHex)((0, import_utils14.randomBytes)(128))}`,
|
|
3934
4469
|
publicInputs: [
|
|
3935
|
-
`0x${(0,
|
|
3936
|
-
`0x${(0,
|
|
4470
|
+
`0x${(0, import_utils14.bytesToHex)(new TextEncoder().encode(intent.intentId))}`,
|
|
4471
|
+
`0x${(0, import_utils14.bytesToHex)(new TextEncoder().encode(quote.quoteId))}`
|
|
3937
4472
|
]
|
|
3938
4473
|
},
|
|
3939
4474
|
fulfilledAt: Math.floor(Date.now() / 1e3)
|
|
@@ -3971,7 +4506,7 @@ function createMockSolver(config) {
|
|
|
3971
4506
|
}
|
|
3972
4507
|
|
|
3973
4508
|
// src/index.ts
|
|
3974
|
-
var
|
|
4509
|
+
var import_types59 = require("@sip-protocol/types");
|
|
3975
4510
|
|
|
3976
4511
|
// src/settlement/interface.ts
|
|
3977
4512
|
var SwapStatus = /* @__PURE__ */ ((SwapStatus2) => {
|
|
@@ -5077,7 +5612,7 @@ function createZcashNativeBackend(config) {
|
|
|
5077
5612
|
|
|
5078
5613
|
// src/settlement/backends/direct-chain.ts
|
|
5079
5614
|
var import_types10 = require("@sip-protocol/types");
|
|
5080
|
-
var
|
|
5615
|
+
var import_utils15 = require("@noble/hashes/utils");
|
|
5081
5616
|
var DEFAULT_GAS_FEES = {
|
|
5082
5617
|
ethereum: 21000n * 50n * 1000000000n,
|
|
5083
5618
|
// 21k gas * 50 gwei = 0.00105 ETH
|
|
@@ -5095,8 +5630,24 @@ var DEFAULT_GAS_FEES = {
|
|
|
5095
5630
|
// 21k gas * 0.001 gwei ETH = 21 gwei = 21e6 wei
|
|
5096
5631
|
base: 2100000000n,
|
|
5097
5632
|
// 21k gas * 0.1 gwei ETH = 2100 gwei = 2.1e9 wei
|
|
5098
|
-
bitcoin: 10000n
|
|
5633
|
+
bitcoin: 10000n,
|
|
5099
5634
|
// 10000 sats = 0.0001 BTC (estimate for 1 input, 2 outputs)
|
|
5635
|
+
aptos: 100n,
|
|
5636
|
+
// 0.000001 APT in octas (gas units)
|
|
5637
|
+
sui: 1000n,
|
|
5638
|
+
// 0.000001 SUI in MIST
|
|
5639
|
+
cosmos: 5000n,
|
|
5640
|
+
// 0.005 ATOM in uatom
|
|
5641
|
+
osmosis: 5000n,
|
|
5642
|
+
// 0.005 OSMO in uosmo
|
|
5643
|
+
injective: 5000n,
|
|
5644
|
+
// 0.000005 INJ in inj (18 decimals)
|
|
5645
|
+
celestia: 5000n,
|
|
5646
|
+
// 0.005 TIA in utia
|
|
5647
|
+
sei: 5000n,
|
|
5648
|
+
// 0.005 SEI in usei
|
|
5649
|
+
dydx: 5000n
|
|
5650
|
+
// 0.000005 DYDX in dydx (18 decimals)
|
|
5100
5651
|
};
|
|
5101
5652
|
|
|
5102
5653
|
// src/zcash/rpc-client.ts
|
|
@@ -6381,33 +6932,321 @@ function createZcashSwapService(config) {
|
|
|
6381
6932
|
var import_types14 = require("@sip-protocol/types");
|
|
6382
6933
|
|
|
6383
6934
|
// src/index.ts
|
|
6384
|
-
var
|
|
6385
|
-
|
|
6386
|
-
// src/payment/payment.ts
|
|
6387
|
-
var import_types15 = require("@sip-protocol/types");
|
|
6388
|
-
var import_sha2569 = require("@noble/hashes/sha256");
|
|
6389
|
-
var import_utils12 = require("@noble/hashes/utils");
|
|
6390
|
-
var import_chacha2 = require("@noble/ciphers/chacha.js");
|
|
6391
|
-
var import_hkdf2 = require("@noble/hashes/hkdf");
|
|
6935
|
+
var import_types60 = require("@sip-protocol/types");
|
|
6392
6936
|
|
|
6393
|
-
// src/
|
|
6394
|
-
var
|
|
6395
|
-
|
|
6396
|
-
|
|
6397
|
-
|
|
6398
|
-
|
|
6399
|
-
|
|
6400
|
-
|
|
6401
|
-
|
|
6402
|
-
|
|
6403
|
-
|
|
6404
|
-
|
|
6405
|
-
|
|
6406
|
-
|
|
6407
|
-
|
|
6408
|
-
|
|
6409
|
-
|
|
6410
|
-
|
|
6937
|
+
// src/bitcoin/taproot.ts
|
|
6938
|
+
var import_secp256k14 = require("@noble/curves/secp256k1");
|
|
6939
|
+
var import_sha25611 = require("@noble/hashes/sha256");
|
|
6940
|
+
var import_utils16 = require("@noble/hashes/utils");
|
|
6941
|
+
var BECH32_CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
|
|
6942
|
+
var BECH32_GENERATOR = [996825010, 642813549, 513874426, 1027748829, 705979059];
|
|
6943
|
+
function taggedHash(tag, data) {
|
|
6944
|
+
const tagHash = (0, import_sha25611.sha256)(new TextEncoder().encode(tag));
|
|
6945
|
+
const taggedData = new Uint8Array(tagHash.length * 2 + data.length);
|
|
6946
|
+
taggedData.set(tagHash, 0);
|
|
6947
|
+
taggedData.set(tagHash, tagHash.length);
|
|
6948
|
+
taggedData.set(data, tagHash.length * 2);
|
|
6949
|
+
return (0, import_sha25611.sha256)(taggedData);
|
|
6950
|
+
}
|
|
6951
|
+
function schnorrSign(message, privateKey, auxRand) {
|
|
6952
|
+
if (message.length !== 32) {
|
|
6953
|
+
throw new ValidationError("message must be 32 bytes", "message");
|
|
6954
|
+
}
|
|
6955
|
+
if (privateKey.length !== 32) {
|
|
6956
|
+
throw new ValidationError("privateKey must be 32 bytes", "privateKey");
|
|
6957
|
+
}
|
|
6958
|
+
if (auxRand && auxRand.length !== 32) {
|
|
6959
|
+
throw new ValidationError("auxRand must be 32 bytes if provided", "auxRand");
|
|
6960
|
+
}
|
|
6961
|
+
return import_secp256k14.schnorr.sign(message, privateKey, auxRand);
|
|
6962
|
+
}
|
|
6963
|
+
function schnorrVerify(signature, message, publicKey) {
|
|
6964
|
+
if (signature.length !== 64) {
|
|
6965
|
+
throw new ValidationError("signature must be 64 bytes", "signature");
|
|
6966
|
+
}
|
|
6967
|
+
if (message.length !== 32) {
|
|
6968
|
+
throw new ValidationError("message must be 32 bytes", "message");
|
|
6969
|
+
}
|
|
6970
|
+
if (publicKey.length !== 32) {
|
|
6971
|
+
throw new ValidationError("publicKey must be 32 bytes (x-only)", "publicKey");
|
|
6972
|
+
}
|
|
6973
|
+
try {
|
|
6974
|
+
return import_secp256k14.schnorr.verify(signature, message, publicKey);
|
|
6975
|
+
} catch {
|
|
6976
|
+
return false;
|
|
6977
|
+
}
|
|
6978
|
+
}
|
|
6979
|
+
function getXOnlyPublicKey(privateKey) {
|
|
6980
|
+
if (privateKey.length !== 32) {
|
|
6981
|
+
throw new ValidationError("privateKey must be 32 bytes", "privateKey");
|
|
6982
|
+
}
|
|
6983
|
+
const publicKey = import_secp256k14.secp256k1.getPublicKey(privateKey, false);
|
|
6984
|
+
return publicKey.slice(1, 33);
|
|
6985
|
+
}
|
|
6986
|
+
function computeTweakedKey(internalKey, merkleRoot) {
|
|
6987
|
+
if (internalKey.length !== 32) {
|
|
6988
|
+
throw new ValidationError("internalKey must be 32 bytes (x-only)", "internalKey");
|
|
6989
|
+
}
|
|
6990
|
+
if (merkleRoot && merkleRoot.length !== 32) {
|
|
6991
|
+
throw new ValidationError("merkleRoot must be 32 bytes if provided", "merkleRoot");
|
|
6992
|
+
}
|
|
6993
|
+
const tweakData = merkleRoot ? new Uint8Array([...internalKey, ...merkleRoot]) : internalKey;
|
|
6994
|
+
const tweak = taggedHash("TapTweak", tweakData);
|
|
6995
|
+
const tweakScalar = BigInt("0x" + (0, import_utils16.bytesToHex)(tweak)) % import_secp256k14.secp256k1.CURVE.n;
|
|
6996
|
+
const internalPoint = import_secp256k14.secp256k1.ProjectivePoint.fromHex(
|
|
6997
|
+
"02" + (0, import_utils16.bytesToHex)(internalKey)
|
|
6998
|
+
);
|
|
6999
|
+
const tweakPoint = import_secp256k14.secp256k1.ProjectivePoint.BASE.multiply(tweakScalar);
|
|
7000
|
+
const tweakedPoint = internalPoint.add(tweakPoint);
|
|
7001
|
+
const tweakedKeyBytes = tweakedPoint.toRawBytes(false);
|
|
7002
|
+
const xOnly = tweakedKeyBytes.slice(1, 33);
|
|
7003
|
+
const yCoord = tweakedKeyBytes.slice(33, 65);
|
|
7004
|
+
const yBigInt = BigInt("0x" + (0, import_utils16.bytesToHex)(yCoord));
|
|
7005
|
+
const parity = Number(yBigInt & 1n);
|
|
7006
|
+
return {
|
|
7007
|
+
tweakedKey: xOnly,
|
|
7008
|
+
parity
|
|
7009
|
+
};
|
|
7010
|
+
}
|
|
7011
|
+
function createTaprootOutput(internalKey, scripts) {
|
|
7012
|
+
if (internalKey.length !== 32) {
|
|
7013
|
+
throw new ValidationError("internalKey must be 32 bytes (x-only)", "internalKey");
|
|
7014
|
+
}
|
|
7015
|
+
let merkleRoot;
|
|
7016
|
+
if (scripts && scripts.length > 0) {
|
|
7017
|
+
if (scripts.length === 1) {
|
|
7018
|
+
const script = scripts[0];
|
|
7019
|
+
const leafData = new Uint8Array([
|
|
7020
|
+
script.leafVersion,
|
|
7021
|
+
script.script.length,
|
|
7022
|
+
...script.script
|
|
7023
|
+
]);
|
|
7024
|
+
merkleRoot = taggedHash("TapLeaf", leafData);
|
|
7025
|
+
} else {
|
|
7026
|
+
throw new ValidationError(
|
|
7027
|
+
"Multiple tapscripts not yet implemented - use single script or no scripts",
|
|
7028
|
+
"scripts"
|
|
7029
|
+
);
|
|
7030
|
+
}
|
|
7031
|
+
}
|
|
7032
|
+
const { tweakedKey, parity } = computeTweakedKey(internalKey, merkleRoot);
|
|
7033
|
+
return {
|
|
7034
|
+
tweakedKey: `0x${(0, import_utils16.bytesToHex)(tweakedKey)}`,
|
|
7035
|
+
internalKey: `0x${(0, import_utils16.bytesToHex)(internalKey)}`,
|
|
7036
|
+
merkleRoot: merkleRoot ? `0x${(0, import_utils16.bytesToHex)(merkleRoot)}` : void 0,
|
|
7037
|
+
parity
|
|
7038
|
+
};
|
|
7039
|
+
}
|
|
7040
|
+
function bech32Polymod(values) {
|
|
7041
|
+
let chk = 1;
|
|
7042
|
+
for (const value of values) {
|
|
7043
|
+
const top = chk >> 25;
|
|
7044
|
+
chk = (chk & 33554431) << 5 ^ value;
|
|
7045
|
+
for (let i = 0; i < 5; i++) {
|
|
7046
|
+
if (top >> i & 1) {
|
|
7047
|
+
chk ^= BECH32_GENERATOR[i];
|
|
7048
|
+
}
|
|
7049
|
+
}
|
|
7050
|
+
}
|
|
7051
|
+
return chk;
|
|
7052
|
+
}
|
|
7053
|
+
function bech32HrpExpand(hrp) {
|
|
7054
|
+
const result = [];
|
|
7055
|
+
for (let i = 0; i < hrp.length; i++) {
|
|
7056
|
+
result.push(hrp.charCodeAt(i) >> 5);
|
|
7057
|
+
}
|
|
7058
|
+
result.push(0);
|
|
7059
|
+
for (let i = 0; i < hrp.length; i++) {
|
|
7060
|
+
result.push(hrp.charCodeAt(i) & 31);
|
|
7061
|
+
}
|
|
7062
|
+
return result;
|
|
7063
|
+
}
|
|
7064
|
+
function bech32VerifyChecksum(hrp, data) {
|
|
7065
|
+
return bech32Polymod([...bech32HrpExpand(hrp), ...data]) === 734539939;
|
|
7066
|
+
}
|
|
7067
|
+
function bech32CreateChecksum(hrp, data) {
|
|
7068
|
+
const values = [...bech32HrpExpand(hrp), ...data, 0, 0, 0, 0, 0, 0];
|
|
7069
|
+
const polymod = bech32Polymod(values) ^ 734539939;
|
|
7070
|
+
const checksum = [];
|
|
7071
|
+
for (let i = 0; i < 6; i++) {
|
|
7072
|
+
checksum.push(polymod >> 5 * (5 - i) & 31);
|
|
7073
|
+
}
|
|
7074
|
+
return checksum;
|
|
7075
|
+
}
|
|
7076
|
+
function convertBits(data, fromBits, toBits, pad) {
|
|
7077
|
+
let acc = 0;
|
|
7078
|
+
let bits = 0;
|
|
7079
|
+
const result = [];
|
|
7080
|
+
const maxv = (1 << toBits) - 1;
|
|
7081
|
+
for (const value of data) {
|
|
7082
|
+
if (value < 0 || value >> fromBits !== 0) {
|
|
7083
|
+
return null;
|
|
7084
|
+
}
|
|
7085
|
+
acc = acc << fromBits | value;
|
|
7086
|
+
bits += fromBits;
|
|
7087
|
+
while (bits >= toBits) {
|
|
7088
|
+
bits -= toBits;
|
|
7089
|
+
result.push(acc >> bits & maxv);
|
|
7090
|
+
}
|
|
7091
|
+
}
|
|
7092
|
+
if (pad) {
|
|
7093
|
+
if (bits > 0) {
|
|
7094
|
+
result.push(acc << toBits - bits & maxv);
|
|
7095
|
+
}
|
|
7096
|
+
} else if (bits >= fromBits || acc << toBits - bits & maxv) {
|
|
7097
|
+
return null;
|
|
7098
|
+
}
|
|
7099
|
+
return result;
|
|
7100
|
+
}
|
|
7101
|
+
function taprootAddress(tweakedKey, network = "mainnet") {
|
|
7102
|
+
if (tweakedKey.length !== 32) {
|
|
7103
|
+
throw new ValidationError("tweakedKey must be 32 bytes", "tweakedKey");
|
|
7104
|
+
}
|
|
7105
|
+
const hrp = network === "mainnet" ? "bc" : network === "testnet" ? "tb" : "bcrt";
|
|
7106
|
+
const version = 1;
|
|
7107
|
+
const words = convertBits(tweakedKey, 8, 5, true);
|
|
7108
|
+
if (!words) {
|
|
7109
|
+
throw new ValidationError("Failed to convert tweaked key to bech32 format", "tweakedKey");
|
|
7110
|
+
}
|
|
7111
|
+
const data = [version, ...words];
|
|
7112
|
+
const checksum = bech32CreateChecksum(hrp, data);
|
|
7113
|
+
const combined = [...data, ...checksum];
|
|
7114
|
+
let result = hrp + "1";
|
|
7115
|
+
for (const value of combined) {
|
|
7116
|
+
result += BECH32_CHARSET[value];
|
|
7117
|
+
}
|
|
7118
|
+
return result;
|
|
7119
|
+
}
|
|
7120
|
+
function decodeTaprootAddress(address) {
|
|
7121
|
+
if (typeof address !== "string" || address.length < 14 || address.length > 90) {
|
|
7122
|
+
throw new ValidationError("Invalid Taproot address format", "address");
|
|
7123
|
+
}
|
|
7124
|
+
const addressLower = address.toLowerCase();
|
|
7125
|
+
const sepIndex = addressLower.lastIndexOf("1");
|
|
7126
|
+
if (sepIndex === -1 || sepIndex + 7 > addressLower.length) {
|
|
7127
|
+
throw new ValidationError("Invalid Taproot address: no separator", "address");
|
|
7128
|
+
}
|
|
7129
|
+
const hrp = addressLower.slice(0, sepIndex);
|
|
7130
|
+
const dataStr = addressLower.slice(sepIndex + 1);
|
|
7131
|
+
let network;
|
|
7132
|
+
if (hrp === "bc") {
|
|
7133
|
+
network = "mainnet";
|
|
7134
|
+
} else if (hrp === "tb") {
|
|
7135
|
+
network = "testnet";
|
|
7136
|
+
} else if (hrp === "bcrt") {
|
|
7137
|
+
network = "regtest";
|
|
7138
|
+
} else {
|
|
7139
|
+
throw new ValidationError(`Unknown HRP: ${hrp}`, "address");
|
|
7140
|
+
}
|
|
7141
|
+
const data = [];
|
|
7142
|
+
for (const char of dataStr) {
|
|
7143
|
+
const index = BECH32_CHARSET.indexOf(char);
|
|
7144
|
+
if (index === -1) {
|
|
7145
|
+
throw new ValidationError(`Invalid bech32 character: ${char}`, "address");
|
|
7146
|
+
}
|
|
7147
|
+
data.push(index);
|
|
7148
|
+
}
|
|
7149
|
+
if (!bech32VerifyChecksum(hrp, data)) {
|
|
7150
|
+
throw new ValidationError("Invalid Taproot address checksum", "address");
|
|
7151
|
+
}
|
|
7152
|
+
const version = data[0];
|
|
7153
|
+
if (version !== 1) {
|
|
7154
|
+
throw new ValidationError(`Expected witness version 1 (Taproot), got ${version}`, "address");
|
|
7155
|
+
}
|
|
7156
|
+
const program = convertBits(new Uint8Array(data.slice(1, -6)), 5, 8, false);
|
|
7157
|
+
if (!program || program.length !== 32) {
|
|
7158
|
+
throw new ValidationError("Invalid Taproot program length", "address");
|
|
7159
|
+
}
|
|
7160
|
+
return {
|
|
7161
|
+
tweakedKey: new Uint8Array(program),
|
|
7162
|
+
network
|
|
7163
|
+
};
|
|
7164
|
+
}
|
|
7165
|
+
function createKeySpendOnlyOutput(privateKey, network = "mainnet") {
|
|
7166
|
+
if (!isValidPrivateKey(privateKey)) {
|
|
7167
|
+
throw new ValidationError("privateKey must be a valid 32-byte hex string", "privateKey");
|
|
7168
|
+
}
|
|
7169
|
+
const privKeyBytes = (0, import_utils16.hexToBytes)(privateKey.slice(2));
|
|
7170
|
+
const internalKey = getXOnlyPublicKey(privKeyBytes);
|
|
7171
|
+
const output = createTaprootOutput(internalKey);
|
|
7172
|
+
const tweakedKeyBytes = (0, import_utils16.hexToBytes)(output.tweakedKey.slice(2));
|
|
7173
|
+
const address = taprootAddress(tweakedKeyBytes, network);
|
|
7174
|
+
return {
|
|
7175
|
+
output,
|
|
7176
|
+
address,
|
|
7177
|
+
internalPrivateKey: privateKey
|
|
7178
|
+
};
|
|
7179
|
+
}
|
|
7180
|
+
function isValidTaprootAddress(address) {
|
|
7181
|
+
try {
|
|
7182
|
+
decodeTaprootAddress(address);
|
|
7183
|
+
return true;
|
|
7184
|
+
} catch {
|
|
7185
|
+
return false;
|
|
7186
|
+
}
|
|
7187
|
+
}
|
|
7188
|
+
function schnorrSignHex(message, privateKey, auxRand) {
|
|
7189
|
+
if (!isValidHex(message)) {
|
|
7190
|
+
throw new ValidationError("message must be a hex string", "message");
|
|
7191
|
+
}
|
|
7192
|
+
if (!isValidPrivateKey(privateKey)) {
|
|
7193
|
+
throw new ValidationError("privateKey must be a valid 32-byte hex string", "privateKey");
|
|
7194
|
+
}
|
|
7195
|
+
if (auxRand && !isValidHex(auxRand)) {
|
|
7196
|
+
throw new ValidationError("auxRand must be a hex string", "auxRand");
|
|
7197
|
+
}
|
|
7198
|
+
const messageBytes = (0, import_utils16.hexToBytes)(message.slice(2));
|
|
7199
|
+
const privateKeyBytes = (0, import_utils16.hexToBytes)(privateKey.slice(2));
|
|
7200
|
+
const auxRandBytes = auxRand ? (0, import_utils16.hexToBytes)(auxRand.slice(2)) : void 0;
|
|
7201
|
+
const signature = schnorrSign(messageBytes, privateKeyBytes, auxRandBytes);
|
|
7202
|
+
return `0x${(0, import_utils16.bytesToHex)(signature)}`;
|
|
7203
|
+
}
|
|
7204
|
+
function schnorrVerifyHex(signature, message, publicKey) {
|
|
7205
|
+
if (!isValidHex(signature)) {
|
|
7206
|
+
throw new ValidationError("signature must be a hex string", "signature");
|
|
7207
|
+
}
|
|
7208
|
+
if (!isValidHex(message)) {
|
|
7209
|
+
throw new ValidationError("message must be a hex string", "message");
|
|
7210
|
+
}
|
|
7211
|
+
if (!isValidHex(publicKey)) {
|
|
7212
|
+
throw new ValidationError("publicKey must be a hex string", "publicKey");
|
|
7213
|
+
}
|
|
7214
|
+
const signatureBytes = (0, import_utils16.hexToBytes)(signature.slice(2));
|
|
7215
|
+
const messageBytes = (0, import_utils16.hexToBytes)(message.slice(2));
|
|
7216
|
+
const publicKeyBytes = (0, import_utils16.hexToBytes)(publicKey.slice(2));
|
|
7217
|
+
return schnorrVerify(signatureBytes, messageBytes, publicKeyBytes);
|
|
7218
|
+
}
|
|
7219
|
+
|
|
7220
|
+
// src/bitcoin/silent-payments.ts
|
|
7221
|
+
var import_secp256k15 = require("@noble/curves/secp256k1");
|
|
7222
|
+
var import_sha25612 = require("@noble/hashes/sha256");
|
|
7223
|
+
var import_utils17 = require("@noble/hashes/utils");
|
|
7224
|
+
|
|
7225
|
+
// src/payment/payment.ts
|
|
7226
|
+
var import_types15 = require("@sip-protocol/types");
|
|
7227
|
+
var import_sha25613 = require("@noble/hashes/sha256");
|
|
7228
|
+
var import_utils18 = require("@noble/hashes/utils");
|
|
7229
|
+
var import_chacha2 = require("@noble/ciphers/chacha.js");
|
|
7230
|
+
var import_hkdf2 = require("@noble/hashes/hkdf");
|
|
7231
|
+
|
|
7232
|
+
// src/payment/stablecoins.ts
|
|
7233
|
+
var STABLECOIN_INFO = {
|
|
7234
|
+
USDC: {
|
|
7235
|
+
symbol: "USDC",
|
|
7236
|
+
name: "USD Coin",
|
|
7237
|
+
issuer: "Circle",
|
|
7238
|
+
type: "fiat-backed",
|
|
7239
|
+
description: "Fully-reserved US dollar stablecoin by Circle"
|
|
7240
|
+
},
|
|
7241
|
+
USDT: {
|
|
7242
|
+
symbol: "USDT",
|
|
7243
|
+
name: "Tether USD",
|
|
7244
|
+
issuer: "Tether",
|
|
7245
|
+
type: "fiat-backed",
|
|
7246
|
+
description: "Largest stablecoin by market cap"
|
|
7247
|
+
},
|
|
7248
|
+
DAI: {
|
|
7249
|
+
symbol: "DAI",
|
|
6411
7250
|
name: "Dai Stablecoin",
|
|
6412
7251
|
issuer: "MakerDAO",
|
|
6413
7252
|
type: "crypto-backed",
|
|
@@ -6882,8 +7721,8 @@ async function createShieldedPayment(params, options) {
|
|
|
6882
7721
|
let viewingKeyHash;
|
|
6883
7722
|
if (viewingKey) {
|
|
6884
7723
|
const keyHex = viewingKey.startsWith("0x") ? viewingKey.slice(2) : viewingKey;
|
|
6885
|
-
const keyBytes = (0,
|
|
6886
|
-
viewingKeyHash = `0x${(0,
|
|
7724
|
+
const keyBytes = (0, import_utils18.hexToBytes)(keyHex);
|
|
7725
|
+
viewingKeyHash = `0x${(0, import_utils18.bytesToHex)((0, import_sha25613.sha256)(keyBytes))}`;
|
|
6887
7726
|
}
|
|
6888
7727
|
const privacyConfig = getPrivacyConfig(
|
|
6889
7728
|
privacy,
|
|
@@ -6923,7 +7762,7 @@ async function createShieldedPayment(params, options) {
|
|
|
6923
7762
|
if (privacy !== import_types15.PrivacyLevel.TRANSPARENT && proofProvider?.isReady) {
|
|
6924
7763
|
const hexToUint8 = (hex) => {
|
|
6925
7764
|
const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
6926
|
-
return (0,
|
|
7765
|
+
return (0, import_utils18.hexToBytes)(cleanHex);
|
|
6927
7766
|
};
|
|
6928
7767
|
const fundingResult = await proofProvider.generateFundingProof({
|
|
6929
7768
|
balance: amount,
|
|
@@ -6950,17 +7789,17 @@ async function createShieldedPayment(params, options) {
|
|
|
6950
7789
|
}
|
|
6951
7790
|
function encryptMemo(memo, viewingKey) {
|
|
6952
7791
|
const keyHex = viewingKey.startsWith("0x") ? viewingKey.slice(2) : viewingKey;
|
|
6953
|
-
const keyBytes = (0,
|
|
6954
|
-
const encKey = (0, import_hkdf2.hkdf)(
|
|
7792
|
+
const keyBytes = (0, import_utils18.hexToBytes)(keyHex);
|
|
7793
|
+
const encKey = (0, import_hkdf2.hkdf)(import_sha25613.sha256, keyBytes, new Uint8Array(0), new Uint8Array(0), 32);
|
|
6955
7794
|
try {
|
|
6956
|
-
const nonce = (0,
|
|
7795
|
+
const nonce = (0, import_utils18.randomBytes)(24);
|
|
6957
7796
|
const cipher = (0, import_chacha2.xchacha20poly1305)(encKey, nonce);
|
|
6958
7797
|
const plaintext = new TextEncoder().encode(memo);
|
|
6959
7798
|
const ciphertext = cipher.encrypt(plaintext);
|
|
6960
7799
|
const result = new Uint8Array(nonce.length + ciphertext.length);
|
|
6961
7800
|
result.set(nonce);
|
|
6962
7801
|
result.set(ciphertext, nonce.length);
|
|
6963
|
-
return `0x${(0,
|
|
7802
|
+
return `0x${(0, import_utils18.bytesToHex)(result)}`;
|
|
6964
7803
|
} finally {
|
|
6965
7804
|
secureWipe(keyBytes);
|
|
6966
7805
|
secureWipe(encKey);
|
|
@@ -6968,11 +7807,11 @@ function encryptMemo(memo, viewingKey) {
|
|
|
6968
7807
|
}
|
|
6969
7808
|
function decryptMemo(encryptedMemo, viewingKey) {
|
|
6970
7809
|
const keyHex = viewingKey.startsWith("0x") ? viewingKey.slice(2) : viewingKey;
|
|
6971
|
-
const keyBytes = (0,
|
|
6972
|
-
const encKey = (0, import_hkdf2.hkdf)(
|
|
7810
|
+
const keyBytes = (0, import_utils18.hexToBytes)(keyHex);
|
|
7811
|
+
const encKey = (0, import_hkdf2.hkdf)(import_sha25613.sha256, keyBytes, new Uint8Array(0), new Uint8Array(0), 32);
|
|
6973
7812
|
try {
|
|
6974
7813
|
const dataHex = encryptedMemo.startsWith("0x") ? encryptedMemo.slice(2) : encryptedMemo;
|
|
6975
|
-
const data = (0,
|
|
7814
|
+
const data = (0, import_utils18.hexToBytes)(dataHex);
|
|
6976
7815
|
const nonce = data.slice(0, 24);
|
|
6977
7816
|
const ciphertext = data.slice(24);
|
|
6978
7817
|
const cipher = (0, import_chacha2.xchacha20poly1305)(encKey, nonce);
|
|
@@ -7020,9 +7859,9 @@ function getPaymentSummary(payment) {
|
|
|
7020
7859
|
|
|
7021
7860
|
// src/treasury/treasury.ts
|
|
7022
7861
|
var import_types16 = require("@sip-protocol/types");
|
|
7023
|
-
var
|
|
7024
|
-
var
|
|
7025
|
-
var
|
|
7862
|
+
var import_secp256k16 = require("@noble/curves/secp256k1");
|
|
7863
|
+
var import_sha25614 = require("@noble/hashes/sha256");
|
|
7864
|
+
var import_utils19 = require("@noble/hashes/utils");
|
|
7026
7865
|
var DEFAULT_PROPOSAL_TTL = 7 * 24 * 60 * 60;
|
|
7027
7866
|
var Treasury = class _Treasury {
|
|
7028
7867
|
config;
|
|
@@ -7513,12 +8352,12 @@ var Treasury = class _Treasury {
|
|
|
7513
8352
|
}
|
|
7514
8353
|
};
|
|
7515
8354
|
function generateTreasuryId() {
|
|
7516
|
-
const bytes = (0,
|
|
7517
|
-
return `treasury_${(0,
|
|
8355
|
+
const bytes = (0, import_utils19.randomBytes)(16);
|
|
8356
|
+
return `treasury_${(0, import_utils19.bytesToHex)(bytes)}`;
|
|
7518
8357
|
}
|
|
7519
8358
|
function generateProposalId() {
|
|
7520
|
-
const bytes = (0,
|
|
7521
|
-
return `prop_${(0,
|
|
8359
|
+
const bytes = (0, import_utils19.randomBytes)(16);
|
|
8360
|
+
return `prop_${(0, import_utils19.bytesToHex)(bytes)}`;
|
|
7522
8361
|
}
|
|
7523
8362
|
function computeProposalHash(proposal) {
|
|
7524
8363
|
const data = JSON.stringify({
|
|
@@ -7530,13 +8369,13 @@ function computeProposalHash(proposal) {
|
|
|
7530
8369
|
createdAt: proposal.createdAt,
|
|
7531
8370
|
expiresAt: proposal.expiresAt
|
|
7532
8371
|
}, (_, value) => typeof value === "bigint" ? value.toString() : value);
|
|
7533
|
-
return (0,
|
|
8372
|
+
return (0, import_sha25614.sha256)(new TextEncoder().encode(data));
|
|
7534
8373
|
}
|
|
7535
8374
|
function signMessage(messageHash, privateKey) {
|
|
7536
8375
|
const keyHex = privateKey.startsWith("0x") ? privateKey.slice(2) : privateKey;
|
|
7537
|
-
const keyBytes = (0,
|
|
8376
|
+
const keyBytes = (0, import_utils19.hexToBytes)(keyHex);
|
|
7538
8377
|
try {
|
|
7539
|
-
const signature =
|
|
8378
|
+
const signature = import_secp256k16.secp256k1.sign(messageHash, keyBytes);
|
|
7540
8379
|
return `0x${signature.toCompactHex()}`;
|
|
7541
8380
|
} finally {
|
|
7542
8381
|
secureWipe(keyBytes);
|
|
@@ -7546,9 +8385,9 @@ function verifySignature(messageHash, signature, publicKey) {
|
|
|
7546
8385
|
const sigHex = signature.startsWith("0x") ? signature.slice(2) : signature;
|
|
7547
8386
|
const pubKeyHex = publicKey.startsWith("0x") ? publicKey.slice(2) : publicKey;
|
|
7548
8387
|
try {
|
|
7549
|
-
const sigBytes = (0,
|
|
7550
|
-
const pubKeyBytes = (0,
|
|
7551
|
-
return
|
|
8388
|
+
const sigBytes = (0, import_utils19.hexToBytes)(sigHex);
|
|
8389
|
+
const pubKeyBytes = (0, import_utils19.hexToBytes)(pubKeyHex);
|
|
8390
|
+
return import_secp256k16.secp256k1.verify(sigBytes, messageHash, pubKeyBytes);
|
|
7552
8391
|
} catch {
|
|
7553
8392
|
return false;
|
|
7554
8393
|
}
|
|
@@ -7706,7 +8545,7 @@ function validateBatchProposalParams(params, config) {
|
|
|
7706
8545
|
|
|
7707
8546
|
// src/compliance/compliance-manager.ts
|
|
7708
8547
|
var import_types17 = require("@sip-protocol/types");
|
|
7709
|
-
var
|
|
8548
|
+
var import_utils20 = require("@noble/hashes/utils");
|
|
7710
8549
|
var DEFAULTS2 = {
|
|
7711
8550
|
riskThreshold: 70,
|
|
7712
8551
|
highValueThreshold: 10000000000n,
|
|
@@ -8127,6 +8966,79 @@ var ComplianceManager = class _ComplianceManager {
|
|
|
8127
8966
|
getAllReports() {
|
|
8128
8967
|
return Array.from(this.reports.values());
|
|
8129
8968
|
}
|
|
8969
|
+
// ─── Dashboard Data API ──────────────────────────────────────────────────────
|
|
8970
|
+
/**
|
|
8971
|
+
* Get list of auditors for dashboard UI
|
|
8972
|
+
*
|
|
8973
|
+
* Returns a simplified view of auditors with essential info.
|
|
8974
|
+
* Alias for getAllAuditors() but returns AuditorRegistration directly.
|
|
8975
|
+
*
|
|
8976
|
+
* @returns Array of auditor registrations
|
|
8977
|
+
*/
|
|
8978
|
+
getAuditorList() {
|
|
8979
|
+
return this.getAllAuditors();
|
|
8980
|
+
}
|
|
8981
|
+
/**
|
|
8982
|
+
* Get pending disclosure requests for dashboard
|
|
8983
|
+
*
|
|
8984
|
+
* Returns disclosure requests waiting for approval/denial.
|
|
8985
|
+
* This is for disclosure REQUESTS, not disclosed transactions.
|
|
8986
|
+
*
|
|
8987
|
+
* @returns Array of pending disclosure requests
|
|
8988
|
+
*/
|
|
8989
|
+
getPendingDisclosures() {
|
|
8990
|
+
return this.getPendingRequests();
|
|
8991
|
+
}
|
|
8992
|
+
/**
|
|
8993
|
+
* Get disclosure history for a specific auditor
|
|
8994
|
+
*
|
|
8995
|
+
* Returns all disclosed transactions that were shared with this auditor,
|
|
8996
|
+
* sorted by disclosure date (most recent first).
|
|
8997
|
+
*
|
|
8998
|
+
* @param auditorId - Auditor ID to get history for
|
|
8999
|
+
* @returns Array of disclosed transactions for this auditor
|
|
9000
|
+
*/
|
|
9001
|
+
getDisclosureHistory(auditorId) {
|
|
9002
|
+
return this.getDisclosedTransactions(auditorId).sort((a, b) => b.disclosedAt - a.disclosedAt);
|
|
9003
|
+
}
|
|
9004
|
+
/**
|
|
9005
|
+
* Get compliance metrics for dashboard
|
|
9006
|
+
*
|
|
9007
|
+
* Calculates key compliance metrics including:
|
|
9008
|
+
* - Total auditors (active + inactive)
|
|
9009
|
+
* - Total disclosures made
|
|
9010
|
+
* - Pending disclosure requests
|
|
9011
|
+
* - Approval rate (approved / total resolved requests)
|
|
9012
|
+
* - Average processing time for disclosure requests
|
|
9013
|
+
*
|
|
9014
|
+
* @returns Compliance metrics object
|
|
9015
|
+
*/
|
|
9016
|
+
getComplianceMetrics() {
|
|
9017
|
+
const allAuditors = this.getAllAuditors();
|
|
9018
|
+
const allDisclosures = this.getDisclosedTransactions();
|
|
9019
|
+
const pendingRequests = this.getPendingRequests();
|
|
9020
|
+
const allRequests = Array.from(this.disclosureRequests.values());
|
|
9021
|
+
const resolvedRequests = allRequests.filter((r) => r.status !== "pending");
|
|
9022
|
+
const approvedRequests = resolvedRequests.filter((r) => r.status === "approved");
|
|
9023
|
+
const approvalRate = resolvedRequests.length > 0 ? approvedRequests.length / resolvedRequests.length : 0;
|
|
9024
|
+
let averageProcessingTime;
|
|
9025
|
+
if (resolvedRequests.length > 0) {
|
|
9026
|
+
const totalProcessingTime = resolvedRequests.reduce((sum, req) => {
|
|
9027
|
+
if (req.resolvedAt) {
|
|
9028
|
+
return sum + (req.resolvedAt - req.requestedAt);
|
|
9029
|
+
}
|
|
9030
|
+
return sum;
|
|
9031
|
+
}, 0);
|
|
9032
|
+
averageProcessingTime = totalProcessingTime / resolvedRequests.length;
|
|
9033
|
+
}
|
|
9034
|
+
return {
|
|
9035
|
+
totalAuditors: allAuditors.length,
|
|
9036
|
+
totalDisclosures: allDisclosures.length,
|
|
9037
|
+
pendingDisclosures: pendingRequests.length,
|
|
9038
|
+
approvalRate,
|
|
9039
|
+
averageProcessingTime
|
|
9040
|
+
};
|
|
9041
|
+
}
|
|
8130
9042
|
// ─── Audit Log ───────────────────────────────────────────────────────────────
|
|
8131
9043
|
/**
|
|
8132
9044
|
* Get audit log entries
|
|
@@ -8325,147 +9237,1767 @@ var ComplianceManager = class _ComplianceManager {
|
|
|
8325
9237
|
highRisk,
|
|
8326
9238
|
flaggedTransactions: flagged
|
|
8327
9239
|
}
|
|
8328
|
-
};
|
|
8329
|
-
if (includeTransactions) {
|
|
8330
|
-
data.transactions = transactions;
|
|
9240
|
+
};
|
|
9241
|
+
if (includeTransactions) {
|
|
9242
|
+
data.transactions = transactions;
|
|
9243
|
+
}
|
|
9244
|
+
return data;
|
|
9245
|
+
}
|
|
9246
|
+
generateCSV(transactions) {
|
|
9247
|
+
const headers = [
|
|
9248
|
+
"Transaction ID",
|
|
9249
|
+
"Disclosure ID",
|
|
9250
|
+
"Type",
|
|
9251
|
+
"Direction",
|
|
9252
|
+
"Token",
|
|
9253
|
+
"Amount",
|
|
9254
|
+
"Sender",
|
|
9255
|
+
"Recipient",
|
|
9256
|
+
"Chain",
|
|
9257
|
+
"Privacy Level",
|
|
9258
|
+
"Timestamp",
|
|
9259
|
+
"TX Hash",
|
|
9260
|
+
"Block",
|
|
9261
|
+
"Risk Score",
|
|
9262
|
+
"Purpose",
|
|
9263
|
+
"Memo"
|
|
9264
|
+
];
|
|
9265
|
+
const rows = transactions.map((tx) => [
|
|
9266
|
+
tx.transactionId,
|
|
9267
|
+
tx.disclosureId,
|
|
9268
|
+
tx.type,
|
|
9269
|
+
tx.direction,
|
|
9270
|
+
tx.token.symbol,
|
|
9271
|
+
tx.amount.toString(),
|
|
9272
|
+
tx.sender,
|
|
9273
|
+
tx.recipient,
|
|
9274
|
+
tx.chain,
|
|
9275
|
+
tx.privacyLevel,
|
|
9276
|
+
new Date(tx.timestamp * 1e3).toISOString(),
|
|
9277
|
+
tx.txHash,
|
|
9278
|
+
tx.blockNumber.toString(),
|
|
9279
|
+
tx.riskScore?.toString() ?? "",
|
|
9280
|
+
tx.purpose ?? "",
|
|
9281
|
+
tx.memo ?? ""
|
|
9282
|
+
]);
|
|
9283
|
+
const escapeForCSV = (val) => {
|
|
9284
|
+
let escaped = val;
|
|
9285
|
+
if (/^[=+\-@|\t]/.test(escaped)) {
|
|
9286
|
+
escaped = `'${escaped}`;
|
|
9287
|
+
}
|
|
9288
|
+
return `"${escaped.replace(/"/g, '""')}"`;
|
|
9289
|
+
};
|
|
9290
|
+
const csvRows = [headers, ...rows].map((row) => row.map(escapeForCSV).join(","));
|
|
9291
|
+
return csvRows.join("\n");
|
|
9292
|
+
}
|
|
9293
|
+
};
|
|
9294
|
+
function generateId(prefix) {
|
|
9295
|
+
return `${prefix}_${(0, import_utils20.bytesToHex)((0, import_utils20.randomBytes)(12))}`;
|
|
9296
|
+
}
|
|
9297
|
+
function validateRegisterAuditorParams(params) {
|
|
9298
|
+
if (!params.organization?.trim()) {
|
|
9299
|
+
throw new ValidationError(
|
|
9300
|
+
"organization is required",
|
|
9301
|
+
"organization",
|
|
9302
|
+
void 0,
|
|
9303
|
+
"SIP_2008" /* MISSING_REQUIRED */
|
|
9304
|
+
);
|
|
9305
|
+
}
|
|
9306
|
+
if (!params.contactName?.trim()) {
|
|
9307
|
+
throw new ValidationError(
|
|
9308
|
+
"contact name is required",
|
|
9309
|
+
"contactName",
|
|
9310
|
+
void 0,
|
|
9311
|
+
"SIP_2008" /* MISSING_REQUIRED */
|
|
9312
|
+
);
|
|
9313
|
+
}
|
|
9314
|
+
if (!params.contactEmail?.trim()) {
|
|
9315
|
+
throw new ValidationError(
|
|
9316
|
+
"contact email is required",
|
|
9317
|
+
"contactEmail",
|
|
9318
|
+
void 0,
|
|
9319
|
+
"SIP_2008" /* MISSING_REQUIRED */
|
|
9320
|
+
);
|
|
9321
|
+
}
|
|
9322
|
+
if (!params.publicKey?.trim()) {
|
|
9323
|
+
throw new ValidationError(
|
|
9324
|
+
"public key is required",
|
|
9325
|
+
"publicKey",
|
|
9326
|
+
void 0,
|
|
9327
|
+
"SIP_2008" /* MISSING_REQUIRED */
|
|
9328
|
+
);
|
|
9329
|
+
}
|
|
9330
|
+
if (!params.scope) {
|
|
9331
|
+
throw new ValidationError(
|
|
9332
|
+
"audit scope is required",
|
|
9333
|
+
"scope",
|
|
9334
|
+
void 0,
|
|
9335
|
+
"SIP_2008" /* MISSING_REQUIRED */
|
|
9336
|
+
);
|
|
9337
|
+
}
|
|
9338
|
+
}
|
|
9339
|
+
function validateReportParams(params) {
|
|
9340
|
+
if (!params.title?.trim()) {
|
|
9341
|
+
throw new ValidationError(
|
|
9342
|
+
"report title is required",
|
|
9343
|
+
"title",
|
|
9344
|
+
void 0,
|
|
9345
|
+
"SIP_2008" /* MISSING_REQUIRED */
|
|
9346
|
+
);
|
|
9347
|
+
}
|
|
9348
|
+
if (!params.type) {
|
|
9349
|
+
throw new ValidationError(
|
|
9350
|
+
"report type is required",
|
|
9351
|
+
"type",
|
|
9352
|
+
void 0,
|
|
9353
|
+
"SIP_2008" /* MISSING_REQUIRED */
|
|
9354
|
+
);
|
|
9355
|
+
}
|
|
9356
|
+
if (!params.format) {
|
|
9357
|
+
throw new ValidationError(
|
|
9358
|
+
"report format is required",
|
|
9359
|
+
"format",
|
|
9360
|
+
void 0,
|
|
9361
|
+
"SIP_2008" /* MISSING_REQUIRED */
|
|
9362
|
+
);
|
|
9363
|
+
}
|
|
9364
|
+
if (params.startDate === void 0 || params.startDate === null || params.endDate === void 0 || params.endDate === null) {
|
|
9365
|
+
throw new ValidationError(
|
|
9366
|
+
"date range is required",
|
|
9367
|
+
"dateRange",
|
|
9368
|
+
void 0,
|
|
9369
|
+
"SIP_2008" /* MISSING_REQUIRED */
|
|
9370
|
+
);
|
|
9371
|
+
}
|
|
9372
|
+
if (params.startDate >= params.endDate) {
|
|
9373
|
+
throw new ValidationError(
|
|
9374
|
+
"start date must be before end date",
|
|
9375
|
+
"dateRange",
|
|
9376
|
+
void 0,
|
|
9377
|
+
"SIP_2001" /* INVALID_INPUT */
|
|
9378
|
+
);
|
|
9379
|
+
}
|
|
9380
|
+
}
|
|
9381
|
+
|
|
9382
|
+
// src/compliance/reports.ts
|
|
9383
|
+
var import_sha25615 = require("@noble/hashes/sha256");
|
|
9384
|
+
var import_utils21 = require("@noble/hashes/utils");
|
|
9385
|
+
|
|
9386
|
+
// src/compliance/pdf.ts
|
|
9387
|
+
function generatePdfReport(report, options = {}) {
|
|
9388
|
+
const {
|
|
9389
|
+
title = "SIP Protocol Audit Report",
|
|
9390
|
+
organization = "",
|
|
9391
|
+
includeTransactions = true,
|
|
9392
|
+
maxTransactions = 100
|
|
9393
|
+
} = options;
|
|
9394
|
+
const content = buildPdfContent(report, {
|
|
9395
|
+
title,
|
|
9396
|
+
organization,
|
|
9397
|
+
includeTransactions,
|
|
9398
|
+
maxTransactions
|
|
9399
|
+
});
|
|
9400
|
+
return generatePdfBinary(content, title);
|
|
9401
|
+
}
|
|
9402
|
+
function buildPdfContent(report, options) {
|
|
9403
|
+
const lines = [];
|
|
9404
|
+
lines.push(options.title);
|
|
9405
|
+
if (options.organization && options.organization.trim() !== "") {
|
|
9406
|
+
lines.push(`Organization: ${options.organization}`);
|
|
9407
|
+
}
|
|
9408
|
+
lines.push(`Report ID: ${report.reportId}`);
|
|
9409
|
+
lines.push(
|
|
9410
|
+
`Generated: ${report.generatedAt.toISOString().replace("T", " ").slice(0, 19)} UTC`
|
|
9411
|
+
);
|
|
9412
|
+
lines.push("");
|
|
9413
|
+
lines.push("Report Period");
|
|
9414
|
+
lines.push(` Start: ${formatDate(report.period.start)}`);
|
|
9415
|
+
lines.push(` End: ${formatDate(report.period.end)}`);
|
|
9416
|
+
lines.push("");
|
|
9417
|
+
lines.push("Summary Statistics");
|
|
9418
|
+
lines.push(` Total Transactions: ${report.summary.transactionCount}`);
|
|
9419
|
+
lines.push(
|
|
9420
|
+
` Total Volume: ${formatBigInt(report.summary.totalVolume)}`
|
|
9421
|
+
);
|
|
9422
|
+
lines.push(
|
|
9423
|
+
` Unique Counterparties: ${report.summary.uniqueCounterparties}`
|
|
9424
|
+
);
|
|
9425
|
+
lines.push("");
|
|
9426
|
+
if (options.includeTransactions && report.transactions.length > 0) {
|
|
9427
|
+
lines.push("Transaction Details");
|
|
9428
|
+
lines.push("");
|
|
9429
|
+
const txToShow = Math.min(
|
|
9430
|
+
report.transactions.length,
|
|
9431
|
+
options.maxTransactions
|
|
9432
|
+
);
|
|
9433
|
+
for (let i = 0; i < txToShow; i++) {
|
|
9434
|
+
const tx = report.transactions[i];
|
|
9435
|
+
lines.push(`Transaction ${i + 1}/${report.transactions.length}`);
|
|
9436
|
+
lines.push(` ID: ${tx.id}`);
|
|
9437
|
+
lines.push(` Sender: ${truncateAddress(tx.sender)}`);
|
|
9438
|
+
lines.push(` Recipient: ${truncateAddress(tx.recipient)}`);
|
|
9439
|
+
lines.push(` Amount: ${formatAmount(tx.amount)}`);
|
|
9440
|
+
lines.push(
|
|
9441
|
+
` Timestamp: ${formatTimestamp(tx.timestamp)}`
|
|
9442
|
+
);
|
|
9443
|
+
if (tx.txHash) {
|
|
9444
|
+
lines.push(` Tx Hash: ${truncateHash(tx.txHash)}`);
|
|
9445
|
+
}
|
|
9446
|
+
if (tx.metadata && Object.keys(tx.metadata).length > 0) {
|
|
9447
|
+
lines.push(` Metadata: ${JSON.stringify(tx.metadata)}`);
|
|
9448
|
+
}
|
|
9449
|
+
lines.push("");
|
|
9450
|
+
}
|
|
9451
|
+
if (report.transactions.length > options.maxTransactions) {
|
|
9452
|
+
lines.push(
|
|
9453
|
+
`... and ${report.transactions.length - options.maxTransactions} more transactions`
|
|
9454
|
+
);
|
|
9455
|
+
lines.push("");
|
|
9456
|
+
}
|
|
9457
|
+
}
|
|
9458
|
+
lines.push("---");
|
|
9459
|
+
lines.push(
|
|
9460
|
+
"This report was generated by SIP Protocol compliance tools."
|
|
9461
|
+
);
|
|
9462
|
+
lines.push("For verification, please contact your compliance officer.");
|
|
9463
|
+
return lines.join("\n");
|
|
9464
|
+
}
|
|
9465
|
+
function generatePdfBinary(content, title) {
|
|
9466
|
+
const objects = [];
|
|
9467
|
+
objects.push(
|
|
9468
|
+
"1 0 obj\n<< /Type /Catalog /Pages 2 0 R >>\nendobj"
|
|
9469
|
+
);
|
|
9470
|
+
objects.push(
|
|
9471
|
+
"2 0 obj\n<< /Type /Pages /Kids [3 0 R] /Count 1 >>\nendobj"
|
|
9472
|
+
);
|
|
9473
|
+
objects.push(
|
|
9474
|
+
"3 0 obj\n<< /Type /Page /Parent 2 0 R /Resources 4 0 R /MediaBox [0 0 612 792] /Contents 5 0 R >>\nendobj"
|
|
9475
|
+
);
|
|
9476
|
+
objects.push(
|
|
9477
|
+
"4 0 obj\n<< /Font << /F1 << /Type /Font /Subtype /Type1 /BaseFont /Courier >> >> >>\nendobj"
|
|
9478
|
+
);
|
|
9479
|
+
const contentStream = buildContentStream(content);
|
|
9480
|
+
objects.push(
|
|
9481
|
+
`5 0 obj
|
|
9482
|
+
<< /Length ${contentStream.length} >>
|
|
9483
|
+
stream
|
|
9484
|
+
${contentStream}
|
|
9485
|
+
endstream
|
|
9486
|
+
endobj`
|
|
9487
|
+
);
|
|
9488
|
+
const now = /* @__PURE__ */ new Date();
|
|
9489
|
+
const pdfDate = formatPdfDate(now);
|
|
9490
|
+
objects.push(
|
|
9491
|
+
`6 0 obj
|
|
9492
|
+
<< /Title (${title}) /Author (SIP Protocol) /Creator (SIP SDK) /CreationDate (${pdfDate}) >>
|
|
9493
|
+
endobj`
|
|
9494
|
+
);
|
|
9495
|
+
const pdfParts = [];
|
|
9496
|
+
pdfParts.push("%PDF-1.4\n%\xE2\xE3\xCF\xD3\n");
|
|
9497
|
+
const xrefOffsets = [0];
|
|
9498
|
+
let currentOffset = pdfParts.join("").length;
|
|
9499
|
+
for (const obj of objects) {
|
|
9500
|
+
xrefOffsets.push(currentOffset);
|
|
9501
|
+
pdfParts.push(obj + "\n");
|
|
9502
|
+
currentOffset = pdfParts.join("").length;
|
|
9503
|
+
}
|
|
9504
|
+
const xrefStart = currentOffset;
|
|
9505
|
+
pdfParts.push("xref\n");
|
|
9506
|
+
pdfParts.push(`0 ${xrefOffsets.length}
|
|
9507
|
+
`);
|
|
9508
|
+
for (let i = 0; i < xrefOffsets.length; i++) {
|
|
9509
|
+
if (i === 0) {
|
|
9510
|
+
pdfParts.push("0000000000 65535 f \n");
|
|
9511
|
+
} else {
|
|
9512
|
+
const offset = String(xrefOffsets[i]).padStart(10, "0");
|
|
9513
|
+
pdfParts.push(`${offset} 00000 n
|
|
9514
|
+
`);
|
|
9515
|
+
}
|
|
9516
|
+
}
|
|
9517
|
+
pdfParts.push("trailer\n");
|
|
9518
|
+
pdfParts.push(
|
|
9519
|
+
`<< /Size ${xrefOffsets.length} /Root 1 0 R /Info 6 0 R >>
|
|
9520
|
+
`
|
|
9521
|
+
);
|
|
9522
|
+
pdfParts.push("startxref\n");
|
|
9523
|
+
pdfParts.push(`${xrefStart}
|
|
9524
|
+
`);
|
|
9525
|
+
pdfParts.push("%%EOF");
|
|
9526
|
+
const pdfString = pdfParts.join("");
|
|
9527
|
+
const encoder = new TextEncoder();
|
|
9528
|
+
return encoder.encode(pdfString);
|
|
9529
|
+
}
|
|
9530
|
+
function buildContentStream(text) {
|
|
9531
|
+
const lines = text.split("\n");
|
|
9532
|
+
const commands = [];
|
|
9533
|
+
commands.push("BT");
|
|
9534
|
+
commands.push("/F1 10 Tf");
|
|
9535
|
+
commands.push("12 TL");
|
|
9536
|
+
let y = 742;
|
|
9537
|
+
for (const line of lines) {
|
|
9538
|
+
commands.push(`50 ${y} Td`);
|
|
9539
|
+
const escaped = escapePdfString(line);
|
|
9540
|
+
commands.push(`(${escaped}) Tj`);
|
|
9541
|
+
y -= 12;
|
|
9542
|
+
if (y < 50) {
|
|
9543
|
+
break;
|
|
9544
|
+
}
|
|
9545
|
+
}
|
|
9546
|
+
commands.push("ET");
|
|
9547
|
+
return commands.join("\n");
|
|
9548
|
+
}
|
|
9549
|
+
function escapePdfString(str) {
|
|
9550
|
+
return str.replace(/\\/g, "\\\\").replace(/\(/g, "\\(").replace(/\)/g, "\\)").replace(/\r/g, "\\r").replace(/\n/g, "\\n");
|
|
9551
|
+
}
|
|
9552
|
+
function formatPdfDate(date) {
|
|
9553
|
+
const year = date.getUTCFullYear();
|
|
9554
|
+
const month = String(date.getUTCMonth() + 1).padStart(2, "0");
|
|
9555
|
+
const day = String(date.getUTCDate()).padStart(2, "0");
|
|
9556
|
+
const hour = String(date.getUTCHours()).padStart(2, "0");
|
|
9557
|
+
const minute = String(date.getUTCMinutes()).padStart(2, "0");
|
|
9558
|
+
const second = String(date.getUTCSeconds()).padStart(2, "0");
|
|
9559
|
+
return `D:${year}${month}${day}${hour}${minute}${second}Z`;
|
|
9560
|
+
}
|
|
9561
|
+
function formatDate(date) {
|
|
9562
|
+
return date.toISOString().split("T")[0];
|
|
9563
|
+
}
|
|
9564
|
+
function formatBigInt(value) {
|
|
9565
|
+
return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
9566
|
+
}
|
|
9567
|
+
function formatAmount(amount) {
|
|
9568
|
+
try {
|
|
9569
|
+
const num = BigInt(amount);
|
|
9570
|
+
return formatBigInt(num);
|
|
9571
|
+
} catch {
|
|
9572
|
+
return amount;
|
|
9573
|
+
}
|
|
9574
|
+
}
|
|
9575
|
+
function formatTimestamp(timestamp) {
|
|
9576
|
+
const date = new Date(timestamp * 1e3);
|
|
9577
|
+
return date.toISOString().replace("T", " ").slice(0, 19) + " UTC";
|
|
9578
|
+
}
|
|
9579
|
+
function truncateAddress(address) {
|
|
9580
|
+
if (address.length <= 12) {
|
|
9581
|
+
return address;
|
|
9582
|
+
}
|
|
9583
|
+
return `${address.slice(0, 6)}...${address.slice(-4)}`;
|
|
9584
|
+
}
|
|
9585
|
+
function truncateHash(hash2) {
|
|
9586
|
+
if (hash2.length <= 16) {
|
|
9587
|
+
return hash2;
|
|
9588
|
+
}
|
|
9589
|
+
return `${hash2.slice(0, 8)}...${hash2.slice(-8)}`;
|
|
9590
|
+
}
|
|
9591
|
+
|
|
9592
|
+
// src/compliance/reports.ts
|
|
9593
|
+
var ComplianceReporter = class {
|
|
9594
|
+
/**
|
|
9595
|
+
* Generate an audit report from encrypted transactions
|
|
9596
|
+
*
|
|
9597
|
+
* Decrypts transactions using the provided viewing key, filters by date range,
|
|
9598
|
+
* and generates a comprehensive report with summary statistics.
|
|
9599
|
+
*
|
|
9600
|
+
* @param params - Report generation parameters
|
|
9601
|
+
* @returns Audit report with decrypted transactions and statistics
|
|
9602
|
+
* @throws {ValidationError} If parameters are invalid
|
|
9603
|
+
* @throws {CryptoError} If decryption fails
|
|
9604
|
+
*/
|
|
9605
|
+
async generateAuditReport(params) {
|
|
9606
|
+
this.validateParams(params);
|
|
9607
|
+
const viewingKey = this.normalizeViewingKey(params.viewingKey);
|
|
9608
|
+
const decryptedTransactions = this.decryptTransactions(
|
|
9609
|
+
params.transactions,
|
|
9610
|
+
viewingKey,
|
|
9611
|
+
params.startDate,
|
|
9612
|
+
params.endDate
|
|
9613
|
+
);
|
|
9614
|
+
const summary = this.calculateSummary(decryptedTransactions);
|
|
9615
|
+
const period = this.determinePeriod(
|
|
9616
|
+
decryptedTransactions,
|
|
9617
|
+
params.startDate,
|
|
9618
|
+
params.endDate
|
|
9619
|
+
);
|
|
9620
|
+
const reportId = `audit_${generateRandomBytes(16).slice(2)}`;
|
|
9621
|
+
return {
|
|
9622
|
+
reportId,
|
|
9623
|
+
generatedAt: /* @__PURE__ */ new Date(),
|
|
9624
|
+
period,
|
|
9625
|
+
transactions: decryptedTransactions,
|
|
9626
|
+
summary
|
|
9627
|
+
};
|
|
9628
|
+
}
|
|
9629
|
+
/**
|
|
9630
|
+
* Validate report generation parameters
|
|
9631
|
+
*/
|
|
9632
|
+
validateParams(params) {
|
|
9633
|
+
if (!params.viewingKey) {
|
|
9634
|
+
throw new ValidationError(
|
|
9635
|
+
"viewingKey is required",
|
|
9636
|
+
"viewingKey",
|
|
9637
|
+
void 0,
|
|
9638
|
+
"SIP_2008" /* MISSING_REQUIRED */
|
|
9639
|
+
);
|
|
9640
|
+
}
|
|
9641
|
+
if (!params.transactions) {
|
|
9642
|
+
throw new ValidationError(
|
|
9643
|
+
"transactions array is required",
|
|
9644
|
+
"transactions",
|
|
9645
|
+
void 0,
|
|
9646
|
+
"SIP_2008" /* MISSING_REQUIRED */
|
|
9647
|
+
);
|
|
9648
|
+
}
|
|
9649
|
+
if (!Array.isArray(params.transactions)) {
|
|
9650
|
+
throw new ValidationError(
|
|
9651
|
+
"transactions must be an array",
|
|
9652
|
+
"transactions",
|
|
9653
|
+
{ received: typeof params.transactions },
|
|
9654
|
+
"SIP_2001" /* INVALID_INPUT */
|
|
9655
|
+
);
|
|
9656
|
+
}
|
|
9657
|
+
if (params.format !== "json" && params.format !== "pdf") {
|
|
9658
|
+
throw new ValidationError(
|
|
9659
|
+
"only JSON and PDF formats are supported",
|
|
9660
|
+
"format",
|
|
9661
|
+
{ received: params.format },
|
|
9662
|
+
"SIP_2001" /* INVALID_INPUT */
|
|
9663
|
+
);
|
|
9664
|
+
}
|
|
9665
|
+
if (params.startDate && params.endDate) {
|
|
9666
|
+
if (params.startDate > params.endDate) {
|
|
9667
|
+
throw new ValidationError(
|
|
9668
|
+
"startDate must be before endDate",
|
|
9669
|
+
"startDate",
|
|
9670
|
+
{
|
|
9671
|
+
startDate: params.startDate.toISOString(),
|
|
9672
|
+
endDate: params.endDate.toISOString()
|
|
9673
|
+
},
|
|
9674
|
+
"SIP_2001" /* INVALID_INPUT */
|
|
9675
|
+
);
|
|
9676
|
+
}
|
|
9677
|
+
}
|
|
9678
|
+
}
|
|
9679
|
+
/**
|
|
9680
|
+
* Normalize viewing key to ViewingKey object
|
|
9681
|
+
*/
|
|
9682
|
+
normalizeViewingKey(viewingKey) {
|
|
9683
|
+
if (typeof viewingKey === "string") {
|
|
9684
|
+
const keyHex = viewingKey.startsWith("0x") ? viewingKey.slice(2) : viewingKey;
|
|
9685
|
+
const keyBytes = (0, import_utils21.hexToBytes)(keyHex);
|
|
9686
|
+
const hashBytes = (0, import_sha25615.sha256)(keyBytes);
|
|
9687
|
+
return {
|
|
9688
|
+
key: `0x${keyHex}`,
|
|
9689
|
+
path: "m/0",
|
|
9690
|
+
hash: `0x${(0, import_utils21.bytesToHex)(hashBytes)}`
|
|
9691
|
+
};
|
|
9692
|
+
}
|
|
9693
|
+
return viewingKey;
|
|
9694
|
+
}
|
|
9695
|
+
/**
|
|
9696
|
+
* Decrypt transactions and filter by date range
|
|
9697
|
+
*/
|
|
9698
|
+
decryptTransactions(encrypted, viewingKey, startDate, endDate) {
|
|
9699
|
+
const decrypted = [];
|
|
9700
|
+
const errors = [];
|
|
9701
|
+
for (let i = 0; i < encrypted.length; i++) {
|
|
9702
|
+
try {
|
|
9703
|
+
const txData = decryptWithViewing(encrypted[i], viewingKey);
|
|
9704
|
+
if (startDate || endDate) {
|
|
9705
|
+
const txDate = new Date(txData.timestamp * 1e3);
|
|
9706
|
+
if (startDate && txDate < startDate) {
|
|
9707
|
+
continue;
|
|
9708
|
+
}
|
|
9709
|
+
if (endDate && txDate > endDate) {
|
|
9710
|
+
continue;
|
|
9711
|
+
}
|
|
9712
|
+
}
|
|
9713
|
+
decrypted.push({
|
|
9714
|
+
id: `tx_${i}`,
|
|
9715
|
+
sender: txData.sender,
|
|
9716
|
+
recipient: txData.recipient,
|
|
9717
|
+
amount: txData.amount,
|
|
9718
|
+
timestamp: txData.timestamp
|
|
9719
|
+
});
|
|
9720
|
+
} catch (error) {
|
|
9721
|
+
errors.push({ index: i, error });
|
|
9722
|
+
}
|
|
9723
|
+
}
|
|
9724
|
+
if (decrypted.length === 0 && encrypted.length > 0) {
|
|
9725
|
+
throw new CryptoError(
|
|
9726
|
+
`Failed to decrypt any transactions. First error: ${errors[0]?.error.message}`,
|
|
9727
|
+
"SIP_3002" /* DECRYPTION_FAILED */,
|
|
9728
|
+
{
|
|
9729
|
+
context: {
|
|
9730
|
+
totalTransactions: encrypted.length,
|
|
9731
|
+
failedCount: errors.length
|
|
9732
|
+
}
|
|
9733
|
+
}
|
|
9734
|
+
);
|
|
9735
|
+
}
|
|
9736
|
+
return decrypted;
|
|
9737
|
+
}
|
|
9738
|
+
/**
|
|
9739
|
+
* Calculate summary statistics
|
|
9740
|
+
*/
|
|
9741
|
+
calculateSummary(transactions) {
|
|
9742
|
+
let totalVolume = 0n;
|
|
9743
|
+
const counterparties = /* @__PURE__ */ new Set();
|
|
9744
|
+
for (const tx of transactions) {
|
|
9745
|
+
try {
|
|
9746
|
+
const amount = BigInt(tx.amount);
|
|
9747
|
+
totalVolume += amount;
|
|
9748
|
+
} catch (error) {
|
|
9749
|
+
console.warn(`Skipping invalid amount in transaction ${tx.id}: ${tx.amount}`);
|
|
9750
|
+
}
|
|
9751
|
+
counterparties.add(tx.sender);
|
|
9752
|
+
counterparties.add(tx.recipient);
|
|
9753
|
+
}
|
|
9754
|
+
return {
|
|
9755
|
+
totalVolume,
|
|
9756
|
+
transactionCount: transactions.length,
|
|
9757
|
+
uniqueCounterparties: counterparties.size
|
|
9758
|
+
};
|
|
9759
|
+
}
|
|
9760
|
+
/**
|
|
9761
|
+
* Determine report period from transactions and params
|
|
9762
|
+
*/
|
|
9763
|
+
determinePeriod(transactions, startDate, endDate) {
|
|
9764
|
+
if (startDate && endDate) {
|
|
9765
|
+
return { start: startDate, end: endDate };
|
|
9766
|
+
}
|
|
9767
|
+
if (transactions.length === 0) {
|
|
9768
|
+
const now = /* @__PURE__ */ new Date();
|
|
9769
|
+
return { start: now, end: now };
|
|
9770
|
+
}
|
|
9771
|
+
let minTimestamp = transactions[0].timestamp;
|
|
9772
|
+
let maxTimestamp = transactions[0].timestamp;
|
|
9773
|
+
for (const tx of transactions) {
|
|
9774
|
+
if (tx.timestamp < minTimestamp) {
|
|
9775
|
+
minTimestamp = tx.timestamp;
|
|
9776
|
+
}
|
|
9777
|
+
if (tx.timestamp > maxTimestamp) {
|
|
9778
|
+
maxTimestamp = tx.timestamp;
|
|
9779
|
+
}
|
|
9780
|
+
}
|
|
9781
|
+
return {
|
|
9782
|
+
start: startDate || new Date(minTimestamp * 1e3),
|
|
9783
|
+
end: endDate || new Date(maxTimestamp * 1e3)
|
|
9784
|
+
};
|
|
9785
|
+
}
|
|
9786
|
+
/**
|
|
9787
|
+
* Export audit report to PDF format
|
|
9788
|
+
*
|
|
9789
|
+
* Generates a professionally formatted PDF document from an audit report.
|
|
9790
|
+
* Works in both Node.js and browser environments.
|
|
9791
|
+
*
|
|
9792
|
+
* @param report - The audit report to export
|
|
9793
|
+
* @param options - PDF export options
|
|
9794
|
+
* @returns PDF document as Uint8Array
|
|
9795
|
+
*
|
|
9796
|
+
* @example
|
|
9797
|
+
* ```typescript
|
|
9798
|
+
* const reporter = new ComplianceReporter()
|
|
9799
|
+
* const report = await reporter.generateAuditReport({...})
|
|
9800
|
+
*
|
|
9801
|
+
* const pdfBytes = reporter.exportToPdf(report, {
|
|
9802
|
+
* title: 'Q1 2025 Audit Report',
|
|
9803
|
+
* organization: 'ACME Corp',
|
|
9804
|
+
* })
|
|
9805
|
+
*
|
|
9806
|
+
* // Save to file (Node.js)
|
|
9807
|
+
* fs.writeFileSync('report.pdf', pdfBytes)
|
|
9808
|
+
* ```
|
|
9809
|
+
*/
|
|
9810
|
+
exportToPdf(report, options) {
|
|
9811
|
+
return generatePdfReport(report, options);
|
|
9812
|
+
}
|
|
9813
|
+
/**
|
|
9814
|
+
* Export transactions to regulatory compliance formats
|
|
9815
|
+
*
|
|
9816
|
+
* Decrypts and exports transactions in formats required by regulators:
|
|
9817
|
+
* - FATF: Financial Action Task Force Travel Rule format
|
|
9818
|
+
* - FINCEN: FinCEN Suspicious Activity Report (SAR) format
|
|
9819
|
+
* - CSV: Generic comma-separated values format
|
|
9820
|
+
*
|
|
9821
|
+
* @param params - Export parameters
|
|
9822
|
+
* @returns Regulatory export in the specified format
|
|
9823
|
+
* @throws {ValidationError} If parameters are invalid
|
|
9824
|
+
* @throws {CryptoError} If decryption fails
|
|
9825
|
+
*
|
|
9826
|
+
* @example
|
|
9827
|
+
* ```typescript
|
|
9828
|
+
* const reporter = new ComplianceReporter()
|
|
9829
|
+
*
|
|
9830
|
+
* // FATF Travel Rule export
|
|
9831
|
+
* const fatfExport = await reporter.exportForRegulator({
|
|
9832
|
+
* viewingKey: myViewingKey,
|
|
9833
|
+
* transactions: encryptedTxs,
|
|
9834
|
+
* jurisdiction: 'EU',
|
|
9835
|
+
* format: 'FATF',
|
|
9836
|
+
* currency: 'EUR',
|
|
9837
|
+
* })
|
|
9838
|
+
*
|
|
9839
|
+
* // FINCEN SAR export (US only)
|
|
9840
|
+
* const fincenExport = await reporter.exportForRegulator({
|
|
9841
|
+
* viewingKey: myViewingKey,
|
|
9842
|
+
* transactions: suspiciousTxs,
|
|
9843
|
+
* jurisdiction: 'US',
|
|
9844
|
+
* format: 'FINCEN',
|
|
9845
|
+
* })
|
|
9846
|
+
*
|
|
9847
|
+
* // CSV export
|
|
9848
|
+
* const csvExport = await reporter.exportForRegulator({
|
|
9849
|
+
* viewingKey: myViewingKey,
|
|
9850
|
+
* transactions: encryptedTxs,
|
|
9851
|
+
* jurisdiction: 'SG',
|
|
9852
|
+
* format: 'CSV',
|
|
9853
|
+
* })
|
|
9854
|
+
* ```
|
|
9855
|
+
*/
|
|
9856
|
+
async exportForRegulator(params) {
|
|
9857
|
+
this.validateRegulatoryParams(params);
|
|
9858
|
+
const viewingKey = this.normalizeViewingKey(params.viewingKey);
|
|
9859
|
+
const decryptedTransactions = this.decryptTransactions(
|
|
9860
|
+
params.transactions,
|
|
9861
|
+
viewingKey,
|
|
9862
|
+
params.startDate,
|
|
9863
|
+
params.endDate
|
|
9864
|
+
);
|
|
9865
|
+
const reportId = `reg_${generateRandomBytes(16).slice(2)}`;
|
|
9866
|
+
switch (params.format) {
|
|
9867
|
+
case "FATF":
|
|
9868
|
+
return this.exportToFATF(
|
|
9869
|
+
reportId,
|
|
9870
|
+
decryptedTransactions,
|
|
9871
|
+
params.jurisdiction,
|
|
9872
|
+
params.currency || "USD"
|
|
9873
|
+
);
|
|
9874
|
+
case "FINCEN":
|
|
9875
|
+
return this.exportToFINCEN(
|
|
9876
|
+
reportId,
|
|
9877
|
+
decryptedTransactions,
|
|
9878
|
+
params.startDate,
|
|
9879
|
+
params.endDate,
|
|
9880
|
+
params.currency || "USD"
|
|
9881
|
+
);
|
|
9882
|
+
case "CSV":
|
|
9883
|
+
return this.exportToCSV(
|
|
9884
|
+
reportId,
|
|
9885
|
+
decryptedTransactions,
|
|
9886
|
+
params.jurisdiction,
|
|
9887
|
+
params.currency || "USD"
|
|
9888
|
+
);
|
|
9889
|
+
default:
|
|
9890
|
+
throw new ValidationError(
|
|
9891
|
+
`unsupported format: ${params.format}`,
|
|
9892
|
+
"format",
|
|
9893
|
+
{ received: params.format },
|
|
9894
|
+
"SIP_2001" /* INVALID_INPUT */
|
|
9895
|
+
);
|
|
9896
|
+
}
|
|
9897
|
+
}
|
|
9898
|
+
/**
|
|
9899
|
+
* Validate regulatory export parameters
|
|
9900
|
+
*/
|
|
9901
|
+
validateRegulatoryParams(params) {
|
|
9902
|
+
if (!params.viewingKey) {
|
|
9903
|
+
throw new ValidationError(
|
|
9904
|
+
"viewingKey is required",
|
|
9905
|
+
"viewingKey",
|
|
9906
|
+
void 0,
|
|
9907
|
+
"SIP_2008" /* MISSING_REQUIRED */
|
|
9908
|
+
);
|
|
9909
|
+
}
|
|
9910
|
+
if (!params.transactions) {
|
|
9911
|
+
throw new ValidationError(
|
|
9912
|
+
"transactions array is required",
|
|
9913
|
+
"transactions",
|
|
9914
|
+
void 0,
|
|
9915
|
+
"SIP_2008" /* MISSING_REQUIRED */
|
|
9916
|
+
);
|
|
9917
|
+
}
|
|
9918
|
+
if (!Array.isArray(params.transactions)) {
|
|
9919
|
+
throw new ValidationError(
|
|
9920
|
+
"transactions must be an array",
|
|
9921
|
+
"transactions",
|
|
9922
|
+
{ received: typeof params.transactions },
|
|
9923
|
+
"SIP_2001" /* INVALID_INPUT */
|
|
9924
|
+
);
|
|
9925
|
+
}
|
|
9926
|
+
if (!params.jurisdiction) {
|
|
9927
|
+
throw new ValidationError(
|
|
9928
|
+
"jurisdiction is required",
|
|
9929
|
+
"jurisdiction",
|
|
9930
|
+
void 0,
|
|
9931
|
+
"SIP_2008" /* MISSING_REQUIRED */
|
|
9932
|
+
);
|
|
9933
|
+
}
|
|
9934
|
+
const validJurisdictions = ["US", "EU", "UK", "SG"];
|
|
9935
|
+
if (!validJurisdictions.includes(params.jurisdiction)) {
|
|
9936
|
+
throw new ValidationError(
|
|
9937
|
+
`invalid jurisdiction. Must be one of: ${validJurisdictions.join(", ")}`,
|
|
9938
|
+
"jurisdiction",
|
|
9939
|
+
{ received: params.jurisdiction },
|
|
9940
|
+
"SIP_2001" /* INVALID_INPUT */
|
|
9941
|
+
);
|
|
9942
|
+
}
|
|
9943
|
+
if (!params.format) {
|
|
9944
|
+
throw new ValidationError(
|
|
9945
|
+
"format is required",
|
|
9946
|
+
"format",
|
|
9947
|
+
void 0,
|
|
9948
|
+
"SIP_2008" /* MISSING_REQUIRED */
|
|
9949
|
+
);
|
|
9950
|
+
}
|
|
9951
|
+
const validFormats = ["FATF", "FINCEN", "CSV"];
|
|
9952
|
+
if (!validFormats.includes(params.format)) {
|
|
9953
|
+
throw new ValidationError(
|
|
9954
|
+
`invalid format. Must be one of: ${validFormats.join(", ")}`,
|
|
9955
|
+
"format",
|
|
9956
|
+
{ received: params.format },
|
|
9957
|
+
"SIP_2001" /* INVALID_INPUT */
|
|
9958
|
+
);
|
|
9959
|
+
}
|
|
9960
|
+
if (params.format === "FINCEN" && params.jurisdiction !== "US") {
|
|
9961
|
+
throw new ValidationError(
|
|
9962
|
+
"FINCEN format is only available for US jurisdiction",
|
|
9963
|
+
"format",
|
|
9964
|
+
{ jurisdiction: params.jurisdiction, format: params.format },
|
|
9965
|
+
"SIP_2001" /* INVALID_INPUT */
|
|
9966
|
+
);
|
|
9967
|
+
}
|
|
9968
|
+
if (params.startDate && params.endDate) {
|
|
9969
|
+
if (params.startDate > params.endDate) {
|
|
9970
|
+
throw new ValidationError(
|
|
9971
|
+
"startDate must be before endDate",
|
|
9972
|
+
"startDate",
|
|
9973
|
+
{
|
|
9974
|
+
startDate: params.startDate.toISOString(),
|
|
9975
|
+
endDate: params.endDate.toISOString()
|
|
9976
|
+
},
|
|
9977
|
+
"SIP_2001" /* INVALID_INPUT */
|
|
9978
|
+
);
|
|
9979
|
+
}
|
|
9980
|
+
}
|
|
9981
|
+
}
|
|
9982
|
+
/**
|
|
9983
|
+
* Export to FATF Travel Rule format
|
|
9984
|
+
*/
|
|
9985
|
+
exportToFATF(reportId, transactions, jurisdiction, currency) {
|
|
9986
|
+
const fatfTransactions = transactions.map((tx) => ({
|
|
9987
|
+
originatorAccount: tx.sender,
|
|
9988
|
+
beneficiaryAccount: tx.recipient,
|
|
9989
|
+
amount: tx.amount,
|
|
9990
|
+
currency,
|
|
9991
|
+
transactionRef: tx.id,
|
|
9992
|
+
timestamp: new Date(tx.timestamp * 1e3).toISOString()
|
|
9993
|
+
}));
|
|
9994
|
+
return {
|
|
9995
|
+
reportId,
|
|
9996
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9997
|
+
jurisdiction,
|
|
9998
|
+
transactions: fatfTransactions
|
|
9999
|
+
};
|
|
10000
|
+
}
|
|
10001
|
+
/**
|
|
10002
|
+
* Export to FINCEN SAR format
|
|
10003
|
+
*/
|
|
10004
|
+
exportToFINCEN(reportId, transactions, startDate, endDate, currency = "USD") {
|
|
10005
|
+
let totalAmount = 0n;
|
|
10006
|
+
for (const tx of transactions) {
|
|
10007
|
+
try {
|
|
10008
|
+
totalAmount += BigInt(tx.amount);
|
|
10009
|
+
} catch (error) {
|
|
10010
|
+
}
|
|
10011
|
+
}
|
|
10012
|
+
const period = this.determinePeriod(transactions, startDate, endDate);
|
|
10013
|
+
const fincenTransactions = transactions.map((tx) => ({
|
|
10014
|
+
transactionDate: new Date(tx.timestamp * 1e3).toISOString(),
|
|
10015
|
+
amount: tx.amount,
|
|
10016
|
+
currency,
|
|
10017
|
+
narrativeSummary: `Transfer from ${tx.sender} to ${tx.recipient}`,
|
|
10018
|
+
transactionRef: tx.id,
|
|
10019
|
+
parties: {
|
|
10020
|
+
sender: tx.sender,
|
|
10021
|
+
recipient: tx.recipient
|
|
10022
|
+
}
|
|
10023
|
+
}));
|
|
10024
|
+
return {
|
|
10025
|
+
reportId,
|
|
10026
|
+
filingType: "SAR",
|
|
10027
|
+
reportDate: (/* @__PURE__ */ new Date()).toISOString(),
|
|
10028
|
+
jurisdiction: "US",
|
|
10029
|
+
summary: {
|
|
10030
|
+
transactionCount: transactions.length,
|
|
10031
|
+
totalAmount: totalAmount.toString(),
|
|
10032
|
+
period: {
|
|
10033
|
+
start: period.start.toISOString(),
|
|
10034
|
+
end: period.end.toISOString()
|
|
10035
|
+
}
|
|
10036
|
+
},
|
|
10037
|
+
transactions: fincenTransactions
|
|
10038
|
+
};
|
|
10039
|
+
}
|
|
10040
|
+
/**
|
|
10041
|
+
* Export to CSV format
|
|
10042
|
+
*/
|
|
10043
|
+
exportToCSV(reportId, transactions, jurisdiction, currency) {
|
|
10044
|
+
const headers = [
|
|
10045
|
+
"Transaction ID",
|
|
10046
|
+
"Timestamp",
|
|
10047
|
+
"Sender",
|
|
10048
|
+
"Recipient",
|
|
10049
|
+
"Amount",
|
|
10050
|
+
"Currency"
|
|
10051
|
+
];
|
|
10052
|
+
const rows = transactions.map((tx) => [
|
|
10053
|
+
tx.id,
|
|
10054
|
+
new Date(tx.timestamp * 1e3).toISOString(),
|
|
10055
|
+
tx.sender,
|
|
10056
|
+
tx.recipient,
|
|
10057
|
+
tx.amount,
|
|
10058
|
+
currency
|
|
10059
|
+
]);
|
|
10060
|
+
return {
|
|
10061
|
+
reportId,
|
|
10062
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
10063
|
+
jurisdiction,
|
|
10064
|
+
headers,
|
|
10065
|
+
rows
|
|
10066
|
+
};
|
|
10067
|
+
}
|
|
10068
|
+
};
|
|
10069
|
+
|
|
10070
|
+
// src/compliance/conditional.ts
|
|
10071
|
+
var import_sha25616 = require("@noble/hashes/sha256");
|
|
10072
|
+
var import_utils22 = require("@noble/hashes/utils");
|
|
10073
|
+
var import_chacha3 = require("@noble/ciphers/chacha.js");
|
|
10074
|
+
var ConditionalDisclosure = class {
|
|
10075
|
+
/**
|
|
10076
|
+
* Create a time-locked disclosure
|
|
10077
|
+
*
|
|
10078
|
+
* Encrypts the viewing key with a deterministic key derived from
|
|
10079
|
+
* the commitment and reveal time. The key can only be reconstructed
|
|
10080
|
+
* after the specified time/block height.
|
|
10081
|
+
*
|
|
10082
|
+
* @param params - Time-lock parameters
|
|
10083
|
+
* @returns Time-lock result with encrypted key
|
|
10084
|
+
* @throws {ValidationError} If parameters are invalid
|
|
10085
|
+
* @throws {CryptoError} If encryption fails
|
|
10086
|
+
*/
|
|
10087
|
+
createTimeLocked(params) {
|
|
10088
|
+
if (!params.viewingKey || !params.viewingKey.startsWith("0x")) {
|
|
10089
|
+
throw new ValidationError(
|
|
10090
|
+
"Invalid viewing key format",
|
|
10091
|
+
"viewingKey",
|
|
10092
|
+
{ viewingKey: params.viewingKey },
|
|
10093
|
+
"SIP_2006" /* INVALID_KEY */
|
|
10094
|
+
);
|
|
10095
|
+
}
|
|
10096
|
+
if (!params.commitment || !params.commitment.startsWith("0x")) {
|
|
10097
|
+
throw new ValidationError(
|
|
10098
|
+
"Invalid commitment format",
|
|
10099
|
+
"commitment",
|
|
10100
|
+
{ commitment: params.commitment },
|
|
10101
|
+
"SIP_3010" /* INVALID_COMMITMENT */
|
|
10102
|
+
);
|
|
10103
|
+
}
|
|
10104
|
+
let revealAfterSeconds;
|
|
10105
|
+
let type;
|
|
10106
|
+
if (params.revealAfter instanceof Date) {
|
|
10107
|
+
revealAfterSeconds = Math.floor(params.revealAfter.getTime() / 1e3);
|
|
10108
|
+
type = "timestamp";
|
|
10109
|
+
} else if (typeof params.revealAfter === "number") {
|
|
10110
|
+
if (params.revealAfter > 1e10) {
|
|
10111
|
+
revealAfterSeconds = Math.floor(params.revealAfter / 1e3);
|
|
10112
|
+
type = "timestamp";
|
|
10113
|
+
} else {
|
|
10114
|
+
revealAfterSeconds = params.revealAfter;
|
|
10115
|
+
type = "blockheight";
|
|
10116
|
+
}
|
|
10117
|
+
if (revealAfterSeconds <= 0) {
|
|
10118
|
+
throw new ValidationError(
|
|
10119
|
+
"Reveal time/block height must be positive",
|
|
10120
|
+
"revealAfter",
|
|
10121
|
+
{ revealAfter: revealAfterSeconds },
|
|
10122
|
+
"SIP_3011" /* INVALID_TIME_LOCK */
|
|
10123
|
+
);
|
|
10124
|
+
}
|
|
10125
|
+
} else {
|
|
10126
|
+
throw new ValidationError(
|
|
10127
|
+
"Invalid revealAfter type (must be Date or number)",
|
|
10128
|
+
"revealAfter",
|
|
10129
|
+
{ revealAfter: params.revealAfter },
|
|
10130
|
+
"SIP_3011" /* INVALID_TIME_LOCK */
|
|
10131
|
+
);
|
|
10132
|
+
}
|
|
10133
|
+
try {
|
|
10134
|
+
const encryptionKey = this._deriveEncryptionKey(
|
|
10135
|
+
params.commitment,
|
|
10136
|
+
revealAfterSeconds
|
|
10137
|
+
);
|
|
10138
|
+
const nonce = (0, import_utils22.randomBytes)(24);
|
|
10139
|
+
const viewingKeyBytes = (0, import_utils22.hexToBytes)(params.viewingKey.slice(2));
|
|
10140
|
+
const cipher = (0, import_chacha3.xchacha20poly1305)(encryptionKey, nonce);
|
|
10141
|
+
const encryptedKey = cipher.encrypt(viewingKeyBytes);
|
|
10142
|
+
const commitmentData = new Uint8Array([
|
|
10143
|
+
...viewingKeyBytes,
|
|
10144
|
+
...this._numberToBytes(revealAfterSeconds)
|
|
10145
|
+
]);
|
|
10146
|
+
const commitmentHash = (0, import_sha25616.sha256)(commitmentData);
|
|
10147
|
+
return {
|
|
10148
|
+
encryptedKey: "0x" + (0, import_utils22.bytesToHex)(encryptedKey),
|
|
10149
|
+
nonce: "0x" + (0, import_utils22.bytesToHex)(nonce),
|
|
10150
|
+
revealAfter: revealAfterSeconds,
|
|
10151
|
+
verificationCommitment: "0x" + (0, import_utils22.bytesToHex)(commitmentHash),
|
|
10152
|
+
encryptionCommitment: params.commitment,
|
|
10153
|
+
type
|
|
10154
|
+
};
|
|
10155
|
+
} catch (error) {
|
|
10156
|
+
if (error instanceof ValidationError) {
|
|
10157
|
+
throw error;
|
|
10158
|
+
}
|
|
10159
|
+
throw new CryptoError(
|
|
10160
|
+
"Failed to create time-locked disclosure",
|
|
10161
|
+
"SIP_3001" /* ENCRYPTION_FAILED */,
|
|
10162
|
+
{
|
|
10163
|
+
cause: error instanceof Error ? error : void 0,
|
|
10164
|
+
operation: "createTimeLocked"
|
|
10165
|
+
}
|
|
10166
|
+
);
|
|
10167
|
+
}
|
|
10168
|
+
}
|
|
10169
|
+
/**
|
|
10170
|
+
* Check if a time-lock is unlocked and retrieve the viewing key
|
|
10171
|
+
*
|
|
10172
|
+
* @param timeLock - Time-lock result to check
|
|
10173
|
+
* @param currentTimeOrBlock - Current time (Date/number) or block height (number)
|
|
10174
|
+
* @returns Unlock result with viewing key if unlocked
|
|
10175
|
+
* @throws {ValidationError} If time-lock format is invalid
|
|
10176
|
+
* @throws {CryptoError} If decryption fails
|
|
10177
|
+
*/
|
|
10178
|
+
checkUnlocked(timeLock, currentTimeOrBlock) {
|
|
10179
|
+
if (!timeLock.encryptedKey || !timeLock.encryptedKey.startsWith("0x")) {
|
|
10180
|
+
throw new ValidationError(
|
|
10181
|
+
"Invalid encrypted key format",
|
|
10182
|
+
"encryptedKey",
|
|
10183
|
+
{ encryptedKey: timeLock.encryptedKey },
|
|
10184
|
+
"SIP_3009" /* INVALID_ENCRYPTED_DATA */
|
|
10185
|
+
);
|
|
10186
|
+
}
|
|
10187
|
+
if (!timeLock.nonce || !timeLock.nonce.startsWith("0x")) {
|
|
10188
|
+
throw new ValidationError(
|
|
10189
|
+
"Invalid nonce format",
|
|
10190
|
+
"nonce",
|
|
10191
|
+
{ nonce: timeLock.nonce },
|
|
10192
|
+
"SIP_3009" /* INVALID_ENCRYPTED_DATA */
|
|
10193
|
+
);
|
|
10194
|
+
}
|
|
10195
|
+
if (!timeLock.verificationCommitment || !timeLock.verificationCommitment.startsWith("0x")) {
|
|
10196
|
+
throw new ValidationError(
|
|
10197
|
+
"Invalid verification commitment format",
|
|
10198
|
+
"verificationCommitment",
|
|
10199
|
+
{ commitment: timeLock.verificationCommitment },
|
|
10200
|
+
"SIP_3010" /* INVALID_COMMITMENT */
|
|
10201
|
+
);
|
|
10202
|
+
}
|
|
10203
|
+
if (!timeLock.encryptionCommitment || !timeLock.encryptionCommitment.startsWith("0x")) {
|
|
10204
|
+
throw new ValidationError(
|
|
10205
|
+
"Invalid encryption commitment format",
|
|
10206
|
+
"encryptionCommitment",
|
|
10207
|
+
{ commitment: timeLock.encryptionCommitment },
|
|
10208
|
+
"SIP_3010" /* INVALID_COMMITMENT */
|
|
10209
|
+
);
|
|
10210
|
+
}
|
|
10211
|
+
let currentValue;
|
|
10212
|
+
if (currentTimeOrBlock instanceof Date) {
|
|
10213
|
+
currentValue = Math.floor(currentTimeOrBlock.getTime() / 1e3);
|
|
10214
|
+
} else if (typeof currentTimeOrBlock === "number") {
|
|
10215
|
+
currentValue = currentTimeOrBlock;
|
|
10216
|
+
} else {
|
|
10217
|
+
currentValue = Math.floor(Date.now() / 1e3);
|
|
10218
|
+
}
|
|
10219
|
+
const unlocked = currentValue >= timeLock.revealAfter;
|
|
10220
|
+
if (!unlocked) {
|
|
10221
|
+
return { unlocked: false };
|
|
10222
|
+
}
|
|
10223
|
+
try {
|
|
10224
|
+
const encryptionKey = this._deriveEncryptionKey(
|
|
10225
|
+
timeLock.encryptionCommitment,
|
|
10226
|
+
timeLock.revealAfter
|
|
10227
|
+
);
|
|
10228
|
+
const nonce = (0, import_utils22.hexToBytes)(timeLock.nonce.slice(2));
|
|
10229
|
+
const encryptedData = (0, import_utils22.hexToBytes)(timeLock.encryptedKey.slice(2));
|
|
10230
|
+
const cipher = (0, import_chacha3.xchacha20poly1305)(encryptionKey, nonce);
|
|
10231
|
+
const decryptedBytes = cipher.decrypt(encryptedData);
|
|
10232
|
+
const viewingKey = "0x" + (0, import_utils22.bytesToHex)(decryptedBytes);
|
|
10233
|
+
return {
|
|
10234
|
+
unlocked: true,
|
|
10235
|
+
viewingKey
|
|
10236
|
+
};
|
|
10237
|
+
} catch (error) {
|
|
10238
|
+
if (error instanceof ValidationError || error instanceof CryptoError) {
|
|
10239
|
+
throw error;
|
|
10240
|
+
}
|
|
10241
|
+
throw new CryptoError(
|
|
10242
|
+
"Failed to decrypt time-locked viewing key",
|
|
10243
|
+
"SIP_3002" /* DECRYPTION_FAILED */,
|
|
10244
|
+
{
|
|
10245
|
+
cause: error instanceof Error ? error : void 0,
|
|
10246
|
+
operation: "checkUnlocked"
|
|
10247
|
+
}
|
|
10248
|
+
);
|
|
10249
|
+
}
|
|
10250
|
+
}
|
|
10251
|
+
/**
|
|
10252
|
+
* Verify a time-lock commitment
|
|
10253
|
+
*
|
|
10254
|
+
* Verifies that the verification commitment in the time-lock matches the hash
|
|
10255
|
+
* of the provided viewing key and reveal time.
|
|
10256
|
+
*
|
|
10257
|
+
* @param timeLock - Time-lock to verify
|
|
10258
|
+
* @param viewingKey - Viewing key to verify against
|
|
10259
|
+
* @returns True if commitment is valid
|
|
10260
|
+
*/
|
|
10261
|
+
verifyCommitment(timeLock, viewingKey) {
|
|
10262
|
+
try {
|
|
10263
|
+
const viewingKeyBytes = (0, import_utils22.hexToBytes)(viewingKey.slice(2));
|
|
10264
|
+
const commitmentData = new Uint8Array([
|
|
10265
|
+
...viewingKeyBytes,
|
|
10266
|
+
...this._numberToBytes(timeLock.revealAfter)
|
|
10267
|
+
]);
|
|
10268
|
+
const expectedCommitment = (0, import_sha25616.sha256)(commitmentData);
|
|
10269
|
+
const actualCommitment = (0, import_utils22.hexToBytes)(timeLock.verificationCommitment.slice(2));
|
|
10270
|
+
if (expectedCommitment.length !== actualCommitment.length) {
|
|
10271
|
+
return false;
|
|
10272
|
+
}
|
|
10273
|
+
let diff = 0;
|
|
10274
|
+
for (let i = 0; i < expectedCommitment.length; i++) {
|
|
10275
|
+
diff |= expectedCommitment[i] ^ actualCommitment[i];
|
|
10276
|
+
}
|
|
10277
|
+
return diff === 0;
|
|
10278
|
+
} catch {
|
|
10279
|
+
return false;
|
|
10280
|
+
}
|
|
10281
|
+
}
|
|
10282
|
+
/**
|
|
10283
|
+
* Derive deterministic encryption key from commitment and reveal time
|
|
10284
|
+
*
|
|
10285
|
+
* @private
|
|
10286
|
+
*/
|
|
10287
|
+
_deriveEncryptionKey(commitment, revealAfter) {
|
|
10288
|
+
const commitmentBytes = (0, import_utils22.hexToBytes)(commitment.slice(2));
|
|
10289
|
+
const timeBytes = this._numberToBytes(revealAfter);
|
|
10290
|
+
const combined = new Uint8Array([...commitmentBytes, ...timeBytes]);
|
|
10291
|
+
const key = (0, import_sha25616.sha256)(combined);
|
|
10292
|
+
if (key.length !== 32) {
|
|
10293
|
+
throw new CryptoError(
|
|
10294
|
+
"Derived key must be 32 bytes",
|
|
10295
|
+
"SIP_3008" /* INVALID_KEY_SIZE */,
|
|
10296
|
+
{
|
|
10297
|
+
context: { actualSize: key.length, expectedSize: 32 },
|
|
10298
|
+
operation: "_deriveEncryptionKey"
|
|
10299
|
+
}
|
|
10300
|
+
);
|
|
10301
|
+
}
|
|
10302
|
+
return key;
|
|
10303
|
+
}
|
|
10304
|
+
/**
|
|
10305
|
+
* Convert number to 8-byte big-endian representation
|
|
10306
|
+
*
|
|
10307
|
+
* @private
|
|
10308
|
+
*/
|
|
10309
|
+
_numberToBytes(num) {
|
|
10310
|
+
const bytes = new Uint8Array(8);
|
|
10311
|
+
const view = new DataView(bytes.buffer);
|
|
10312
|
+
view.setBigUint64(0, BigInt(Math.floor(num)), false);
|
|
10313
|
+
return bytes;
|
|
10314
|
+
}
|
|
10315
|
+
};
|
|
10316
|
+
|
|
10317
|
+
// src/compliance/conditional-threshold.ts
|
|
10318
|
+
var import_secp256k17 = require("@noble/curves/secp256k1");
|
|
10319
|
+
var import_sha25617 = require("@noble/hashes/sha256");
|
|
10320
|
+
var import_utils23 = require("@noble/hashes/utils");
|
|
10321
|
+
var CURVE_ORDER2 = import_secp256k17.secp256k1.CURVE.n;
|
|
10322
|
+
|
|
10323
|
+
// src/compliance/threshold.ts
|
|
10324
|
+
var import_sha25618 = require("@noble/hashes/sha256");
|
|
10325
|
+
var import_utils24 = require("@noble/hashes/utils");
|
|
10326
|
+
var FIELD_PRIME = 2n ** 256n - 189n;
|
|
10327
|
+
var ThresholdViewingKey = class {
|
|
10328
|
+
/**
|
|
10329
|
+
* Create threshold shares from a viewing key
|
|
10330
|
+
*
|
|
10331
|
+
* @param params - Configuration parameters
|
|
10332
|
+
* @returns Threshold shares with commitment
|
|
10333
|
+
* @throws ValidationError if parameters are invalid
|
|
10334
|
+
*
|
|
10335
|
+
* @example
|
|
10336
|
+
* ```typescript
|
|
10337
|
+
* const threshold = ThresholdViewingKey.create({
|
|
10338
|
+
* threshold: 3,
|
|
10339
|
+
* totalShares: 5,
|
|
10340
|
+
* viewingKey: '0xabc123...',
|
|
10341
|
+
* })
|
|
10342
|
+
* ```
|
|
10343
|
+
*/
|
|
10344
|
+
static create(params) {
|
|
10345
|
+
this.validateParams(params.threshold, params.totalShares);
|
|
10346
|
+
this.validateViewingKey(params.viewingKey);
|
|
10347
|
+
const secret = this.viewingKeyToSecret(params.viewingKey);
|
|
10348
|
+
const keyLength = params.viewingKey.slice(2).length;
|
|
10349
|
+
const coefficients = this.generateCoefficients(params.threshold, secret);
|
|
10350
|
+
const commitment = this.createCommitment(secret, coefficients);
|
|
10351
|
+
const shares = [];
|
|
10352
|
+
for (let i = 1; i <= params.totalShares; i++) {
|
|
10353
|
+
const x = BigInt(i);
|
|
10354
|
+
const y = this.evaluatePolynomial(coefficients, x);
|
|
10355
|
+
shares.push(this.encodeShare(x, y, keyLength, commitment));
|
|
10356
|
+
}
|
|
10357
|
+
return {
|
|
10358
|
+
shares,
|
|
10359
|
+
commitment,
|
|
10360
|
+
threshold: params.threshold,
|
|
10361
|
+
totalShares: params.totalShares
|
|
10362
|
+
};
|
|
10363
|
+
}
|
|
10364
|
+
/**
|
|
10365
|
+
* Reconstruct viewing key from threshold shares
|
|
10366
|
+
*
|
|
10367
|
+
* @param shares - Array of encoded shares (must be >= threshold)
|
|
10368
|
+
* @returns Reconstructed viewing key
|
|
10369
|
+
* @throws ValidationError if insufficient or invalid shares
|
|
10370
|
+
*
|
|
10371
|
+
* @example
|
|
10372
|
+
* ```typescript
|
|
10373
|
+
* const viewingKey = ThresholdViewingKey.reconstruct([
|
|
10374
|
+
* 'share1',
|
|
10375
|
+
* 'share2',
|
|
10376
|
+
* 'share3',
|
|
10377
|
+
* ])
|
|
10378
|
+
* ```
|
|
10379
|
+
*/
|
|
10380
|
+
static reconstruct(shares) {
|
|
10381
|
+
if (!shares || shares.length === 0) {
|
|
10382
|
+
throw new ValidationError(
|
|
10383
|
+
"at least one share is required",
|
|
10384
|
+
"shares",
|
|
10385
|
+
{ received: shares },
|
|
10386
|
+
"SIP_2008" /* MISSING_REQUIRED */
|
|
10387
|
+
);
|
|
10388
|
+
}
|
|
10389
|
+
const decodedShares = shares.map((s) => this.decodeShare(s));
|
|
10390
|
+
const commitment = decodedShares[0].commitment;
|
|
10391
|
+
const keyLength = decodedShares[0].keyLength;
|
|
10392
|
+
for (const share of decodedShares) {
|
|
10393
|
+
if (share.commitment !== commitment) {
|
|
10394
|
+
throw new ValidationError(
|
|
10395
|
+
"shares must all have the same commitment",
|
|
10396
|
+
"shares",
|
|
10397
|
+
{ commitment },
|
|
10398
|
+
"SIP_3012" /* INVALID_SHARE */
|
|
10399
|
+
);
|
|
10400
|
+
}
|
|
10401
|
+
if (share.keyLength !== keyLength) {
|
|
10402
|
+
throw new ValidationError(
|
|
10403
|
+
"shares must all have the same key length",
|
|
10404
|
+
"shares",
|
|
10405
|
+
{ keyLength },
|
|
10406
|
+
"SIP_3012" /* INVALID_SHARE */
|
|
10407
|
+
);
|
|
10408
|
+
}
|
|
10409
|
+
}
|
|
10410
|
+
const xCoords = new Set(decodedShares.map((s) => s.x.toString()));
|
|
10411
|
+
if (xCoords.size !== decodedShares.length) {
|
|
10412
|
+
throw new ValidationError(
|
|
10413
|
+
"shares must have unique x-coordinates",
|
|
10414
|
+
"shares",
|
|
10415
|
+
void 0,
|
|
10416
|
+
"SIP_3012" /* INVALID_SHARE */
|
|
10417
|
+
);
|
|
10418
|
+
}
|
|
10419
|
+
const secret = this.lagrangeInterpolate(decodedShares);
|
|
10420
|
+
return this.secretToViewingKey(secret, keyLength);
|
|
10421
|
+
}
|
|
10422
|
+
/**
|
|
10423
|
+
* Verify a share without revealing the viewing key
|
|
10424
|
+
*
|
|
10425
|
+
* @param share - Encoded share to verify
|
|
10426
|
+
* @param expectedCommitment - Expected commitment hash
|
|
10427
|
+
* @returns True if share is valid
|
|
10428
|
+
*
|
|
10429
|
+
* @example
|
|
10430
|
+
* ```typescript
|
|
10431
|
+
* const isValid = ThresholdViewingKey.verifyShare(
|
|
10432
|
+
* 'share1',
|
|
10433
|
+
* 'commitment_hash'
|
|
10434
|
+
* )
|
|
10435
|
+
* ```
|
|
10436
|
+
*/
|
|
10437
|
+
static verifyShare(share, expectedCommitment) {
|
|
10438
|
+
try {
|
|
10439
|
+
const decoded = this.decodeShare(share);
|
|
10440
|
+
return decoded.commitment === expectedCommitment;
|
|
10441
|
+
} catch {
|
|
10442
|
+
return false;
|
|
10443
|
+
}
|
|
10444
|
+
}
|
|
10445
|
+
// ─── Private Helper Methods ─────────────────────────────────────────────────
|
|
10446
|
+
/**
|
|
10447
|
+
* Validate threshold and total shares parameters
|
|
10448
|
+
*/
|
|
10449
|
+
static validateParams(threshold, totalShares) {
|
|
10450
|
+
if (!Number.isInteger(threshold) || threshold < 2) {
|
|
10451
|
+
throw new ValidationError(
|
|
10452
|
+
"threshold must be an integer >= 2",
|
|
10453
|
+
"threshold",
|
|
10454
|
+
{ received: threshold },
|
|
10455
|
+
"SIP_3013" /* INVALID_THRESHOLD */
|
|
10456
|
+
);
|
|
10457
|
+
}
|
|
10458
|
+
if (!Number.isInteger(totalShares) || totalShares < threshold) {
|
|
10459
|
+
throw new ValidationError(
|
|
10460
|
+
"totalShares must be an integer >= threshold",
|
|
10461
|
+
"totalShares",
|
|
10462
|
+
{ received: totalShares, threshold },
|
|
10463
|
+
"SIP_3013" /* INVALID_THRESHOLD */
|
|
10464
|
+
);
|
|
10465
|
+
}
|
|
10466
|
+
if (totalShares > 255) {
|
|
10467
|
+
throw new ValidationError(
|
|
10468
|
+
"totalShares must be <= 255",
|
|
10469
|
+
"totalShares",
|
|
10470
|
+
{ received: totalShares },
|
|
10471
|
+
"SIP_3013" /* INVALID_THRESHOLD */
|
|
10472
|
+
);
|
|
10473
|
+
}
|
|
10474
|
+
}
|
|
10475
|
+
/**
|
|
10476
|
+
* Validate viewing key format
|
|
10477
|
+
*/
|
|
10478
|
+
static validateViewingKey(viewingKey) {
|
|
10479
|
+
if (!viewingKey || typeof viewingKey !== "string") {
|
|
10480
|
+
throw new ValidationError(
|
|
10481
|
+
"viewingKey is required",
|
|
10482
|
+
"viewingKey",
|
|
10483
|
+
{ received: viewingKey },
|
|
10484
|
+
"SIP_2008" /* MISSING_REQUIRED */
|
|
10485
|
+
);
|
|
10486
|
+
}
|
|
10487
|
+
if (!viewingKey.startsWith("0x")) {
|
|
10488
|
+
throw new ValidationError(
|
|
10489
|
+
"viewingKey must be hex-encoded (start with 0x)",
|
|
10490
|
+
"viewingKey",
|
|
10491
|
+
{ received: viewingKey },
|
|
10492
|
+
"SIP_3015" /* INVALID_FORMAT */
|
|
10493
|
+
);
|
|
10494
|
+
}
|
|
10495
|
+
if (viewingKey.length < 66) {
|
|
10496
|
+
throw new ValidationError(
|
|
10497
|
+
"viewingKey must be at least 32 bytes",
|
|
10498
|
+
"viewingKey",
|
|
10499
|
+
{ received: viewingKey.length },
|
|
10500
|
+
"SIP_3015" /* INVALID_FORMAT */
|
|
10501
|
+
);
|
|
10502
|
+
}
|
|
10503
|
+
}
|
|
10504
|
+
/**
|
|
10505
|
+
* Convert viewing key to secret (bigint)
|
|
10506
|
+
*/
|
|
10507
|
+
static viewingKeyToSecret(viewingKey) {
|
|
10508
|
+
const bytes = (0, import_utils24.hexToBytes)(viewingKey.slice(2));
|
|
10509
|
+
let secret = 0n;
|
|
10510
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
10511
|
+
secret = secret << 8n | BigInt(bytes[i]);
|
|
10512
|
+
}
|
|
10513
|
+
return this.mod(secret, FIELD_PRIME);
|
|
10514
|
+
}
|
|
10515
|
+
/**
|
|
10516
|
+
* Convert secret (bigint) back to viewing key
|
|
10517
|
+
* @param secret - The secret as bigint
|
|
10518
|
+
* @param hexLength - Length of the hex string (without 0x prefix)
|
|
10519
|
+
*/
|
|
10520
|
+
static secretToViewingKey(secret, hexLength) {
|
|
10521
|
+
let hex = secret.toString(16);
|
|
10522
|
+
hex = hex.padStart(hexLength, "0");
|
|
10523
|
+
return `0x${hex}`;
|
|
10524
|
+
}
|
|
10525
|
+
/**
|
|
10526
|
+
* Generate random polynomial coefficients
|
|
10527
|
+
* Polynomial: f(x) = a₀ + a₁x + a₂x² + ... + aₙ₋₁xⁿ⁻¹
|
|
10528
|
+
* where a₀ = secret
|
|
10529
|
+
*/
|
|
10530
|
+
static generateCoefficients(threshold, secret) {
|
|
10531
|
+
const coefficients = [secret];
|
|
10532
|
+
for (let i = 1; i < threshold; i++) {
|
|
10533
|
+
const randomCoeff = this.randomFieldElement();
|
|
10534
|
+
coefficients.push(randomCoeff);
|
|
10535
|
+
}
|
|
10536
|
+
return coefficients;
|
|
10537
|
+
}
|
|
10538
|
+
/**
|
|
10539
|
+
* Generate a random field element
|
|
10540
|
+
*/
|
|
10541
|
+
static randomFieldElement() {
|
|
10542
|
+
const bytes = (0, import_utils24.randomBytes)(32);
|
|
10543
|
+
let value = 0n;
|
|
10544
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
10545
|
+
value = value << 8n | BigInt(bytes[i]);
|
|
10546
|
+
}
|
|
10547
|
+
return this.mod(value, FIELD_PRIME);
|
|
10548
|
+
}
|
|
10549
|
+
/**
|
|
10550
|
+
* Evaluate polynomial at point x
|
|
10551
|
+
* f(x) = a₀ + a₁x + a₂x² + ... + aₙ₋₁xⁿ⁻¹
|
|
10552
|
+
*/
|
|
10553
|
+
static evaluatePolynomial(coefficients, x) {
|
|
10554
|
+
let result = 0n;
|
|
10555
|
+
let xPower = 1n;
|
|
10556
|
+
for (const coeff of coefficients) {
|
|
10557
|
+
result = this.mod(result + this.mod(coeff * xPower, FIELD_PRIME), FIELD_PRIME);
|
|
10558
|
+
xPower = this.mod(xPower * x, FIELD_PRIME);
|
|
10559
|
+
}
|
|
10560
|
+
return result;
|
|
10561
|
+
}
|
|
10562
|
+
/**
|
|
10563
|
+
* Create commitment hash from secret and coefficients
|
|
10564
|
+
*/
|
|
10565
|
+
static createCommitment(secret, coefficients) {
|
|
10566
|
+
const data = [secret, ...coefficients].map((c) => c.toString(16).padStart(64, "0")).join("");
|
|
10567
|
+
const hash2 = (0, import_sha25618.sha256)((0, import_utils24.hexToBytes)(data));
|
|
10568
|
+
return (0, import_utils24.bytesToHex)(hash2);
|
|
10569
|
+
}
|
|
10570
|
+
/**
|
|
10571
|
+
* Encode share as string: "x:y:len:commitment"
|
|
10572
|
+
*/
|
|
10573
|
+
static encodeShare(x, y, keyLength, commitment) {
|
|
10574
|
+
const xHex = x.toString(16).padStart(2, "0");
|
|
10575
|
+
const yHex = y.toString(16).padStart(64, "0");
|
|
10576
|
+
const lenHex = keyLength.toString(16).padStart(4, "0");
|
|
10577
|
+
return `${xHex}:${yHex}:${lenHex}:${commitment}`;
|
|
10578
|
+
}
|
|
10579
|
+
/**
|
|
10580
|
+
* Decode share from string
|
|
10581
|
+
*/
|
|
10582
|
+
static decodeShare(share) {
|
|
10583
|
+
if (!share || typeof share !== "string") {
|
|
10584
|
+
throw new ValidationError(
|
|
10585
|
+
"share must be a non-empty string",
|
|
10586
|
+
"share",
|
|
10587
|
+
{ received: share },
|
|
10588
|
+
"SIP_3012" /* INVALID_SHARE */
|
|
10589
|
+
);
|
|
10590
|
+
}
|
|
10591
|
+
const parts = share.split(":");
|
|
10592
|
+
if (parts.length !== 4) {
|
|
10593
|
+
throw new ValidationError(
|
|
10594
|
+
'share must have format "x:y:len:commitment"',
|
|
10595
|
+
"share",
|
|
10596
|
+
{ received: share },
|
|
10597
|
+
"SIP_3012" /* INVALID_SHARE */
|
|
10598
|
+
);
|
|
10599
|
+
}
|
|
10600
|
+
const [xHex, yHex, lenHex, commitment] = parts;
|
|
10601
|
+
try {
|
|
10602
|
+
const x = BigInt(`0x${xHex}`);
|
|
10603
|
+
const y = BigInt(`0x${yHex}`);
|
|
10604
|
+
const keyLength = parseInt(lenHex, 16);
|
|
10605
|
+
if (x <= 0n) {
|
|
10606
|
+
throw new ValidationError(
|
|
10607
|
+
"share x-coordinate must be positive",
|
|
10608
|
+
"share",
|
|
10609
|
+
{ x },
|
|
10610
|
+
"SIP_3012" /* INVALID_SHARE */
|
|
10611
|
+
);
|
|
10612
|
+
}
|
|
10613
|
+
if (keyLength < 64) {
|
|
10614
|
+
throw new ValidationError(
|
|
10615
|
+
"key length must be at least 64 (32 bytes)",
|
|
10616
|
+
"share",
|
|
10617
|
+
{ keyLength },
|
|
10618
|
+
"SIP_3012" /* INVALID_SHARE */
|
|
10619
|
+
);
|
|
10620
|
+
}
|
|
10621
|
+
return { x, y, keyLength, commitment };
|
|
10622
|
+
} catch (error) {
|
|
10623
|
+
throw new ValidationError(
|
|
10624
|
+
"failed to decode share",
|
|
10625
|
+
"share",
|
|
10626
|
+
{ error: error.message },
|
|
10627
|
+
"SIP_3012" /* INVALID_SHARE */
|
|
10628
|
+
);
|
|
8331
10629
|
}
|
|
8332
|
-
return data;
|
|
8333
10630
|
}
|
|
8334
|
-
|
|
8335
|
-
|
|
8336
|
-
|
|
8337
|
-
|
|
8338
|
-
|
|
8339
|
-
|
|
8340
|
-
|
|
8341
|
-
|
|
8342
|
-
|
|
8343
|
-
|
|
8344
|
-
|
|
8345
|
-
|
|
8346
|
-
|
|
8347
|
-
|
|
8348
|
-
|
|
8349
|
-
|
|
8350
|
-
"Purpose",
|
|
8351
|
-
"Memo"
|
|
8352
|
-
];
|
|
8353
|
-
const rows = transactions.map((tx) => [
|
|
8354
|
-
tx.transactionId,
|
|
8355
|
-
tx.disclosureId,
|
|
8356
|
-
tx.type,
|
|
8357
|
-
tx.direction,
|
|
8358
|
-
tx.token.symbol,
|
|
8359
|
-
tx.amount.toString(),
|
|
8360
|
-
tx.sender,
|
|
8361
|
-
tx.recipient,
|
|
8362
|
-
tx.chain,
|
|
8363
|
-
tx.privacyLevel,
|
|
8364
|
-
new Date(tx.timestamp * 1e3).toISOString(),
|
|
8365
|
-
tx.txHash,
|
|
8366
|
-
tx.blockNumber.toString(),
|
|
8367
|
-
tx.riskScore?.toString() ?? "",
|
|
8368
|
-
tx.purpose ?? "",
|
|
8369
|
-
tx.memo ?? ""
|
|
8370
|
-
]);
|
|
8371
|
-
const escapeForCSV = (val) => {
|
|
8372
|
-
let escaped = val;
|
|
8373
|
-
if (/^[=+\-@|\t]/.test(escaped)) {
|
|
8374
|
-
escaped = `'${escaped}`;
|
|
10631
|
+
/**
|
|
10632
|
+
* Lagrange interpolation to reconstruct secret
|
|
10633
|
+
* Evaluates polynomial at x=0 to get f(0) = secret
|
|
10634
|
+
*/
|
|
10635
|
+
static lagrangeInterpolate(shares) {
|
|
10636
|
+
let secret = 0n;
|
|
10637
|
+
for (let i = 0; i < shares.length; i++) {
|
|
10638
|
+
const xi = shares[i].x;
|
|
10639
|
+
const yi = shares[i].y;
|
|
10640
|
+
let numerator = 1n;
|
|
10641
|
+
let denominator = 1n;
|
|
10642
|
+
for (let j = 0; j < shares.length; j++) {
|
|
10643
|
+
if (i === j) continue;
|
|
10644
|
+
const xj = shares[j].x;
|
|
10645
|
+
numerator = this.mod(numerator * this.mod(-xj, FIELD_PRIME), FIELD_PRIME);
|
|
10646
|
+
denominator = this.mod(denominator * this.mod(xi - xj, FIELD_PRIME), FIELD_PRIME);
|
|
8375
10647
|
}
|
|
8376
|
-
|
|
8377
|
-
|
|
8378
|
-
|
|
8379
|
-
return
|
|
10648
|
+
const coeff = this.mod(numerator * this.modInverse(denominator, FIELD_PRIME), FIELD_PRIME);
|
|
10649
|
+
secret = this.mod(secret + this.mod(yi * coeff, FIELD_PRIME), FIELD_PRIME);
|
|
10650
|
+
}
|
|
10651
|
+
return secret;
|
|
8380
10652
|
}
|
|
8381
|
-
|
|
8382
|
-
|
|
8383
|
-
|
|
8384
|
-
|
|
8385
|
-
|
|
8386
|
-
if (!params.organization?.trim()) {
|
|
8387
|
-
throw new ValidationError(
|
|
8388
|
-
"organization is required",
|
|
8389
|
-
"organization",
|
|
8390
|
-
void 0,
|
|
8391
|
-
"SIP_2008" /* MISSING_REQUIRED */
|
|
8392
|
-
);
|
|
10653
|
+
/**
|
|
10654
|
+
* Modular arithmetic: a mod m
|
|
10655
|
+
*/
|
|
10656
|
+
static mod(a, m) {
|
|
10657
|
+
return (a % m + m) % m;
|
|
8393
10658
|
}
|
|
8394
|
-
|
|
8395
|
-
|
|
8396
|
-
|
|
8397
|
-
|
|
8398
|
-
|
|
8399
|
-
|
|
8400
|
-
)
|
|
10659
|
+
/**
|
|
10660
|
+
* Modular multiplicative inverse using Extended Euclidean Algorithm
|
|
10661
|
+
* Returns x such that (a * x) mod m = 1
|
|
10662
|
+
*/
|
|
10663
|
+
static modInverse(a, m) {
|
|
10664
|
+
const a0 = this.mod(a, m);
|
|
10665
|
+
if (a0 === 0n) {
|
|
10666
|
+
throw new CryptoError(
|
|
10667
|
+
"modular inverse does not exist (a = 0)",
|
|
10668
|
+
"SIP_3014" /* CRYPTO_OPERATION_FAILED */,
|
|
10669
|
+
{ operation: "modInverse" }
|
|
10670
|
+
);
|
|
10671
|
+
}
|
|
10672
|
+
let [old_r, r] = [a0, m];
|
|
10673
|
+
let [old_s, s] = [1n, 0n];
|
|
10674
|
+
while (r !== 0n) {
|
|
10675
|
+
const quotient = old_r / r;
|
|
10676
|
+
[old_r, r] = [r, old_r - quotient * r];
|
|
10677
|
+
[old_s, s] = [s, old_s - quotient * s];
|
|
10678
|
+
}
|
|
10679
|
+
if (old_r !== 1n) {
|
|
10680
|
+
throw new CryptoError(
|
|
10681
|
+
"modular inverse does not exist (gcd != 1)",
|
|
10682
|
+
"SIP_3014" /* CRYPTO_OPERATION_FAILED */,
|
|
10683
|
+
{ operation: "modInverse" }
|
|
10684
|
+
);
|
|
10685
|
+
}
|
|
10686
|
+
return this.mod(old_s, m);
|
|
8401
10687
|
}
|
|
8402
|
-
|
|
8403
|
-
|
|
8404
|
-
|
|
8405
|
-
|
|
8406
|
-
|
|
8407
|
-
|
|
8408
|
-
|
|
10688
|
+
};
|
|
10689
|
+
|
|
10690
|
+
// src/compliance/derivation.ts
|
|
10691
|
+
var import_sha25619 = require("@noble/hashes/sha256");
|
|
10692
|
+
var import_sha5123 = require("@noble/hashes/sha512");
|
|
10693
|
+
var import_hmac2 = require("@noble/hashes/hmac");
|
|
10694
|
+
var import_utils25 = require("@noble/hashes/utils");
|
|
10695
|
+
var AuditorType = /* @__PURE__ */ ((AuditorType2) => {
|
|
10696
|
+
AuditorType2[AuditorType2["PRIMARY"] = 0] = "PRIMARY";
|
|
10697
|
+
AuditorType2[AuditorType2["REGULATORY"] = 1] = "REGULATORY";
|
|
10698
|
+
AuditorType2[AuditorType2["INTERNAL"] = 2] = "INTERNAL";
|
|
10699
|
+
AuditorType2[AuditorType2["TAX"] = 3] = "TAX";
|
|
10700
|
+
return AuditorType2;
|
|
10701
|
+
})(AuditorType || {});
|
|
10702
|
+
var AuditorKeyDerivation = class {
|
|
10703
|
+
/**
|
|
10704
|
+
* SIP Protocol coin type (BIP-44 registered)
|
|
10705
|
+
*
|
|
10706
|
+
* Note: This is a placeholder. In production, register with SLIP-44:
|
|
10707
|
+
* https://github.com/satoshilabs/slips/blob/master/slip-0044.md
|
|
10708
|
+
*/
|
|
10709
|
+
static COIN_TYPE = 1234;
|
|
10710
|
+
/**
|
|
10711
|
+
* BIP-44 purpose field
|
|
10712
|
+
*/
|
|
10713
|
+
static PURPOSE = 44;
|
|
10714
|
+
/**
|
|
10715
|
+
* Hardened derivation flag (2^31)
|
|
10716
|
+
*/
|
|
10717
|
+
static HARDENED = 2147483648;
|
|
10718
|
+
/**
|
|
10719
|
+
* Generate BIP-44 derivation path
|
|
10720
|
+
*
|
|
10721
|
+
* @param auditorType - Type of auditor key
|
|
10722
|
+
* @param account - Account index (default: 0)
|
|
10723
|
+
* @returns BIP-44 style path string
|
|
10724
|
+
*
|
|
10725
|
+
* @example
|
|
10726
|
+
* ```typescript
|
|
10727
|
+
* AuditorKeyDerivation.derivePath(AuditorType.REGULATORY)
|
|
10728
|
+
* // Returns: "m/44'/1234'/0'/1"
|
|
10729
|
+
*
|
|
10730
|
+
* AuditorKeyDerivation.derivePath(AuditorType.TAX, 5)
|
|
10731
|
+
* // Returns: "m/44'/1234'/5'/3"
|
|
10732
|
+
* ```
|
|
10733
|
+
*/
|
|
10734
|
+
static derivePath(auditorType, account = 0) {
|
|
10735
|
+
this.validateAuditorType(auditorType);
|
|
10736
|
+
this.validateAccount(account);
|
|
10737
|
+
return `m/${this.PURPOSE}'/${this.COIN_TYPE}'/${account}'/${auditorType}`;
|
|
8409
10738
|
}
|
|
8410
|
-
|
|
8411
|
-
|
|
8412
|
-
|
|
8413
|
-
|
|
8414
|
-
|
|
8415
|
-
|
|
8416
|
-
|
|
10739
|
+
/**
|
|
10740
|
+
* Derive a viewing key for an auditor
|
|
10741
|
+
*
|
|
10742
|
+
* Uses BIP-32 style hierarchical deterministic key derivation:
|
|
10743
|
+
* 1. Derive master key from seed
|
|
10744
|
+
* 2. Harden purpose (44')
|
|
10745
|
+
* 3. Harden coin type (1234')
|
|
10746
|
+
* 4. Harden account index
|
|
10747
|
+
* 5. Derive auditor type (non-hardened)
|
|
10748
|
+
*
|
|
10749
|
+
* @param params - Derivation parameters
|
|
10750
|
+
* @returns Derived viewing key with metadata
|
|
10751
|
+
*
|
|
10752
|
+
* @throws {ValidationError} If parameters are invalid
|
|
10753
|
+
*
|
|
10754
|
+
* @example
|
|
10755
|
+
* ```typescript
|
|
10756
|
+
* const regulatoryKey = AuditorKeyDerivation.deriveViewingKey({
|
|
10757
|
+
* masterSeed: randomBytes(32),
|
|
10758
|
+
* auditorType: AuditorType.REGULATORY,
|
|
10759
|
+
* })
|
|
10760
|
+
*
|
|
10761
|
+
* console.log(regulatoryKey.path) // "m/44'/1234'/0'/1"
|
|
10762
|
+
* console.log(regulatoryKey.viewingKey.key) // "0x..."
|
|
10763
|
+
* ```
|
|
10764
|
+
*/
|
|
10765
|
+
static deriveViewingKey(params) {
|
|
10766
|
+
const { masterSeed, auditorType, account = 0 } = params;
|
|
10767
|
+
this.validateMasterSeed(masterSeed);
|
|
10768
|
+
this.validateAuditorType(auditorType);
|
|
10769
|
+
this.validateAccount(account);
|
|
10770
|
+
const path = this.derivePath(auditorType, account);
|
|
10771
|
+
const indices = [
|
|
10772
|
+
this.PURPOSE | this.HARDENED,
|
|
10773
|
+
// 44' (hardened)
|
|
10774
|
+
this.COIN_TYPE | this.HARDENED,
|
|
10775
|
+
// 1234' (hardened)
|
|
10776
|
+
account | this.HARDENED,
|
|
10777
|
+
// account' (hardened)
|
|
10778
|
+
auditorType
|
|
10779
|
+
// auditorType (non-hardened)
|
|
10780
|
+
];
|
|
10781
|
+
const masterData = (0, import_hmac2.hmac)(import_sha5123.sha512, (0, import_utils25.utf8ToBytes)("SIP-MASTER-SEED"), masterSeed);
|
|
10782
|
+
let currentKey = new Uint8Array(masterData.slice(0, 32));
|
|
10783
|
+
let chainCode = new Uint8Array(masterData.slice(32, 64));
|
|
10784
|
+
try {
|
|
10785
|
+
for (let i = 0; i < indices.length; i++) {
|
|
10786
|
+
const index = indices[i];
|
|
10787
|
+
const derived = this.deriveChildKey(currentKey, chainCode, index);
|
|
10788
|
+
if (i > 0) {
|
|
10789
|
+
secureWipe(currentKey);
|
|
10790
|
+
}
|
|
10791
|
+
currentKey = new Uint8Array(derived.key);
|
|
10792
|
+
chainCode = new Uint8Array(derived.chainCode);
|
|
10793
|
+
}
|
|
10794
|
+
const keyHex = `0x${(0, import_utils25.bytesToHex)(currentKey)}`;
|
|
10795
|
+
const hashBytes = (0, import_sha25619.sha256)(currentKey);
|
|
10796
|
+
const hash2 = `0x${(0, import_utils25.bytesToHex)(hashBytes)}`;
|
|
10797
|
+
const viewingKey = {
|
|
10798
|
+
key: keyHex,
|
|
10799
|
+
path,
|
|
10800
|
+
hash: hash2
|
|
10801
|
+
};
|
|
10802
|
+
return {
|
|
10803
|
+
path,
|
|
10804
|
+
viewingKey,
|
|
10805
|
+
auditorType,
|
|
10806
|
+
account
|
|
10807
|
+
};
|
|
10808
|
+
} finally {
|
|
10809
|
+
secureWipe(currentKey);
|
|
10810
|
+
secureWipe(chainCode);
|
|
10811
|
+
}
|
|
8417
10812
|
}
|
|
8418
|
-
|
|
8419
|
-
|
|
8420
|
-
|
|
8421
|
-
|
|
8422
|
-
|
|
8423
|
-
|
|
8424
|
-
|
|
10813
|
+
/**
|
|
10814
|
+
* Derive multiple viewing keys at once
|
|
10815
|
+
*
|
|
10816
|
+
* Efficiently derives keys for multiple auditor types from the same
|
|
10817
|
+
* master seed. This is more efficient than calling deriveViewingKey
|
|
10818
|
+
* multiple times as it reuses intermediate derivations.
|
|
10819
|
+
*
|
|
10820
|
+
* @param params - Derivation parameters
|
|
10821
|
+
* @returns Array of derived viewing keys
|
|
10822
|
+
*
|
|
10823
|
+
* @example
|
|
10824
|
+
* ```typescript
|
|
10825
|
+
* const keys = AuditorKeyDerivation.deriveMultiple({
|
|
10826
|
+
* masterSeed: randomBytes(32),
|
|
10827
|
+
* auditorTypes: [
|
|
10828
|
+
* AuditorType.PRIMARY,
|
|
10829
|
+
* AuditorType.REGULATORY,
|
|
10830
|
+
* AuditorType.INTERNAL,
|
|
10831
|
+
* ],
|
|
10832
|
+
* })
|
|
10833
|
+
*
|
|
10834
|
+
* // keys[0] -> PRIMARY key (m/44'/1234'/0'/0)
|
|
10835
|
+
* // keys[1] -> REGULATORY key (m/44'/1234'/0'/1)
|
|
10836
|
+
* // keys[2] -> INTERNAL key (m/44'/1234'/0'/2)
|
|
10837
|
+
* ```
|
|
10838
|
+
*/
|
|
10839
|
+
static deriveMultiple(params) {
|
|
10840
|
+
const { masterSeed, auditorTypes, account = 0 } = params;
|
|
10841
|
+
this.validateMasterSeed(masterSeed);
|
|
10842
|
+
this.validateAccount(account);
|
|
10843
|
+
if (!auditorTypes || auditorTypes.length === 0) {
|
|
10844
|
+
throw new ValidationError(
|
|
10845
|
+
"at least one auditor type is required",
|
|
10846
|
+
"auditorTypes",
|
|
10847
|
+
{ received: auditorTypes },
|
|
10848
|
+
"SIP_2008" /* MISSING_REQUIRED */
|
|
10849
|
+
);
|
|
10850
|
+
}
|
|
10851
|
+
for (const type of auditorTypes) {
|
|
10852
|
+
this.validateAuditorType(type);
|
|
10853
|
+
}
|
|
10854
|
+
const uniqueTypes = Array.from(new Set(auditorTypes));
|
|
10855
|
+
const commonIndices = [
|
|
10856
|
+
this.PURPOSE | this.HARDENED,
|
|
10857
|
+
// 44' (hardened)
|
|
10858
|
+
this.COIN_TYPE | this.HARDENED,
|
|
10859
|
+
// 1234' (hardened)
|
|
10860
|
+
account | this.HARDENED
|
|
10861
|
+
// account' (hardened)
|
|
10862
|
+
];
|
|
10863
|
+
const masterData = (0, import_hmac2.hmac)(import_sha5123.sha512, (0, import_utils25.utf8ToBytes)("SIP-MASTER-SEED"), masterSeed);
|
|
10864
|
+
let commonKey = new Uint8Array(masterData.slice(0, 32));
|
|
10865
|
+
let commonChainCode = new Uint8Array(masterData.slice(32, 64));
|
|
10866
|
+
try {
|
|
10867
|
+
for (let i = 0; i < commonIndices.length; i++) {
|
|
10868
|
+
const index = commonIndices[i];
|
|
10869
|
+
const derived = this.deriveChildKey(commonKey, commonChainCode, index);
|
|
10870
|
+
if (i > 0) {
|
|
10871
|
+
secureWipe(commonKey);
|
|
10872
|
+
}
|
|
10873
|
+
commonKey = new Uint8Array(derived.key);
|
|
10874
|
+
commonChainCode = new Uint8Array(derived.chainCode);
|
|
10875
|
+
}
|
|
10876
|
+
const results = [];
|
|
10877
|
+
for (const auditorType of uniqueTypes) {
|
|
10878
|
+
const derived = this.deriveChildKey(commonKey, commonChainCode, auditorType);
|
|
10879
|
+
try {
|
|
10880
|
+
const keyHex = `0x${(0, import_utils25.bytesToHex)(derived.key)}`;
|
|
10881
|
+
const hashBytes = (0, import_sha25619.sha256)(derived.key);
|
|
10882
|
+
const hash2 = `0x${(0, import_utils25.bytesToHex)(hashBytes)}`;
|
|
10883
|
+
const path = this.derivePath(auditorType, account);
|
|
10884
|
+
const viewingKey = {
|
|
10885
|
+
key: keyHex,
|
|
10886
|
+
path,
|
|
10887
|
+
hash: hash2
|
|
10888
|
+
};
|
|
10889
|
+
results.push({
|
|
10890
|
+
path,
|
|
10891
|
+
viewingKey,
|
|
10892
|
+
auditorType,
|
|
10893
|
+
account
|
|
10894
|
+
});
|
|
10895
|
+
} finally {
|
|
10896
|
+
secureWipe(derived.key);
|
|
10897
|
+
secureWipe(derived.chainCode);
|
|
10898
|
+
}
|
|
10899
|
+
}
|
|
10900
|
+
return results;
|
|
10901
|
+
} finally {
|
|
10902
|
+
secureWipe(commonKey);
|
|
10903
|
+
secureWipe(commonChainCode);
|
|
10904
|
+
}
|
|
8425
10905
|
}
|
|
8426
|
-
|
|
8427
|
-
|
|
8428
|
-
|
|
8429
|
-
|
|
8430
|
-
|
|
8431
|
-
|
|
8432
|
-
|
|
8433
|
-
|
|
8434
|
-
|
|
10906
|
+
/**
|
|
10907
|
+
* Get human-readable name for auditor type
|
|
10908
|
+
*
|
|
10909
|
+
* @param auditorType - Auditor type enum value
|
|
10910
|
+
* @returns Friendly name string
|
|
10911
|
+
*/
|
|
10912
|
+
static getAuditorTypeName(auditorType) {
|
|
10913
|
+
switch (auditorType) {
|
|
10914
|
+
case 0 /* PRIMARY */:
|
|
10915
|
+
return "Primary";
|
|
10916
|
+
case 1 /* REGULATORY */:
|
|
10917
|
+
return "Regulatory";
|
|
10918
|
+
case 2 /* INTERNAL */:
|
|
10919
|
+
return "Internal";
|
|
10920
|
+
case 3 /* TAX */:
|
|
10921
|
+
return "Tax Authority";
|
|
10922
|
+
default:
|
|
10923
|
+
return `Unknown (${auditorType})`;
|
|
10924
|
+
}
|
|
8435
10925
|
}
|
|
8436
|
-
|
|
8437
|
-
|
|
8438
|
-
|
|
8439
|
-
|
|
8440
|
-
|
|
8441
|
-
|
|
8442
|
-
|
|
10926
|
+
// ─── Private Helpers ─────────────────────────────────────────────────────────
|
|
10927
|
+
/**
|
|
10928
|
+
* Derive a child key using BIP-32 HMAC-SHA512 derivation
|
|
10929
|
+
*
|
|
10930
|
+
* @param parentKey - Parent key bytes (32 bytes)
|
|
10931
|
+
* @param chainCode - Parent chain code (32 bytes)
|
|
10932
|
+
* @param index - Child index (use | HARDENED for hardened derivation)
|
|
10933
|
+
* @returns Derived key and chain code
|
|
10934
|
+
*/
|
|
10935
|
+
static deriveChildKey(parentKey, chainCode, index) {
|
|
10936
|
+
const isHardened = (index & this.HARDENED) !== 0;
|
|
10937
|
+
const data = new Uint8Array(37);
|
|
10938
|
+
if (isHardened) {
|
|
10939
|
+
data[0] = 0;
|
|
10940
|
+
data.set(parentKey, 1);
|
|
10941
|
+
} else {
|
|
10942
|
+
data[0] = 1;
|
|
10943
|
+
data.set(parentKey, 1);
|
|
10944
|
+
}
|
|
10945
|
+
const indexView = new DataView(data.buffer, 33, 4);
|
|
10946
|
+
indexView.setUint32(0, index, false);
|
|
10947
|
+
const hmacResult = (0, import_hmac2.hmac)(import_sha5123.sha512, chainCode, data);
|
|
10948
|
+
const childKey = new Uint8Array(hmacResult.slice(0, 32));
|
|
10949
|
+
const childChainCode = new Uint8Array(hmacResult.slice(32, 64));
|
|
10950
|
+
return {
|
|
10951
|
+
key: childKey,
|
|
10952
|
+
chainCode: childChainCode
|
|
10953
|
+
};
|
|
8443
10954
|
}
|
|
8444
|
-
|
|
8445
|
-
|
|
8446
|
-
|
|
8447
|
-
|
|
8448
|
-
|
|
8449
|
-
|
|
8450
|
-
|
|
10955
|
+
/**
|
|
10956
|
+
* Validate master seed
|
|
10957
|
+
*/
|
|
10958
|
+
static validateMasterSeed(seed) {
|
|
10959
|
+
if (!seed || seed.length < 32) {
|
|
10960
|
+
throw new ValidationError(
|
|
10961
|
+
"master seed must be at least 32 bytes",
|
|
10962
|
+
"masterSeed",
|
|
10963
|
+
{ received: seed?.length ?? 0 },
|
|
10964
|
+
"SIP_2001" /* INVALID_INPUT */
|
|
10965
|
+
);
|
|
10966
|
+
}
|
|
8451
10967
|
}
|
|
8452
|
-
|
|
8453
|
-
|
|
8454
|
-
|
|
8455
|
-
|
|
8456
|
-
|
|
8457
|
-
|
|
8458
|
-
|
|
10968
|
+
/**
|
|
10969
|
+
* Validate auditor type
|
|
10970
|
+
*/
|
|
10971
|
+
static validateAuditorType(type) {
|
|
10972
|
+
const validTypes = [
|
|
10973
|
+
0 /* PRIMARY */,
|
|
10974
|
+
1 /* REGULATORY */,
|
|
10975
|
+
2 /* INTERNAL */,
|
|
10976
|
+
3 /* TAX */
|
|
10977
|
+
];
|
|
10978
|
+
if (!validTypes.includes(type)) {
|
|
10979
|
+
throw new ValidationError(
|
|
10980
|
+
`invalid auditor type: ${type}`,
|
|
10981
|
+
"auditorType",
|
|
10982
|
+
{ received: type, valid: validTypes },
|
|
10983
|
+
"SIP_2001" /* INVALID_INPUT */
|
|
10984
|
+
);
|
|
10985
|
+
}
|
|
8459
10986
|
}
|
|
8460
|
-
|
|
8461
|
-
|
|
8462
|
-
|
|
8463
|
-
|
|
8464
|
-
|
|
8465
|
-
|
|
8466
|
-
|
|
10987
|
+
/**
|
|
10988
|
+
* Validate account index
|
|
10989
|
+
*/
|
|
10990
|
+
static validateAccount(account) {
|
|
10991
|
+
if (!Number.isInteger(account) || account < 0 || account >= this.HARDENED) {
|
|
10992
|
+
throw new ValidationError(
|
|
10993
|
+
`account must be a non-negative integer less than ${this.HARDENED}`,
|
|
10994
|
+
"account",
|
|
10995
|
+
{ received: account },
|
|
10996
|
+
"SIP_2001" /* INVALID_INPUT */
|
|
10997
|
+
);
|
|
10998
|
+
}
|
|
8467
10999
|
}
|
|
8468
|
-
}
|
|
11000
|
+
};
|
|
8469
11001
|
|
|
8470
11002
|
// src/wallet/errors.ts
|
|
8471
11003
|
var import_types18 = require("@sip-protocol/types");
|
|
@@ -10624,6 +13156,30 @@ function createMockEthereumProvider(config = {}) {
|
|
|
10624
13156
|
return provider;
|
|
10625
13157
|
}
|
|
10626
13158
|
|
|
13159
|
+
// src/wallet/cosmos/adapter.ts
|
|
13160
|
+
var import_types29 = require("@sip-protocol/types");
|
|
13161
|
+
|
|
13162
|
+
// src/wallet/cosmos/mock.ts
|
|
13163
|
+
var import_types31 = require("@sip-protocol/types");
|
|
13164
|
+
|
|
13165
|
+
// src/wallet/bitcoin/adapter.ts
|
|
13166
|
+
var import_types34 = require("@sip-protocol/types");
|
|
13167
|
+
|
|
13168
|
+
// src/wallet/bitcoin/mock.ts
|
|
13169
|
+
var import_types36 = require("@sip-protocol/types");
|
|
13170
|
+
|
|
13171
|
+
// src/wallet/aptos/adapter.ts
|
|
13172
|
+
var import_types39 = require("@sip-protocol/types");
|
|
13173
|
+
|
|
13174
|
+
// src/wallet/aptos/mock.ts
|
|
13175
|
+
var import_types41 = require("@sip-protocol/types");
|
|
13176
|
+
|
|
13177
|
+
// src/wallet/sui/adapter.ts
|
|
13178
|
+
var import_types43 = require("@sip-protocol/types");
|
|
13179
|
+
|
|
13180
|
+
// src/wallet/sui/mock.ts
|
|
13181
|
+
var import_types45 = require("@sip-protocol/types");
|
|
13182
|
+
|
|
10627
13183
|
// src/wallet/hardware/types.ts
|
|
10628
13184
|
var DerivationPath = {
|
|
10629
13185
|
/** Ethereum: m/44'/60'/0'/0/index */
|
|
@@ -10699,7 +13255,7 @@ function getAvailableTransports() {
|
|
|
10699
13255
|
}
|
|
10700
13256
|
|
|
10701
13257
|
// src/wallet/hardware/ledger.ts
|
|
10702
|
-
var
|
|
13258
|
+
var import_types47 = require("@sip-protocol/types");
|
|
10703
13259
|
var LedgerWalletAdapter = class extends BaseWalletAdapter {
|
|
10704
13260
|
chain;
|
|
10705
13261
|
name = "ledger";
|
|
@@ -10852,7 +13408,7 @@ var LedgerWalletAdapter = class extends BaseWalletAdapter {
|
|
|
10852
13408
|
async getBalance() {
|
|
10853
13409
|
throw new WalletError(
|
|
10854
13410
|
"Hardware wallets do not track balances. Use an RPC provider.",
|
|
10855
|
-
|
|
13411
|
+
import_types47.WalletErrorCode.UNSUPPORTED_OPERATION
|
|
10856
13412
|
);
|
|
10857
13413
|
}
|
|
10858
13414
|
/**
|
|
@@ -10863,7 +13419,7 @@ var LedgerWalletAdapter = class extends BaseWalletAdapter {
|
|
|
10863
13419
|
async getTokenBalance(_asset) {
|
|
10864
13420
|
throw new WalletError(
|
|
10865
13421
|
"Hardware wallets do not track balances. Use an RPC provider.",
|
|
10866
|
-
|
|
13422
|
+
import_types47.WalletErrorCode.UNSUPPORTED_OPERATION
|
|
10867
13423
|
);
|
|
10868
13424
|
}
|
|
10869
13425
|
// ─── Account Management ─────────────────────────────────────────────────────
|
|
@@ -11151,7 +13707,7 @@ function createLedgerAdapter(config) {
|
|
|
11151
13707
|
}
|
|
11152
13708
|
|
|
11153
13709
|
// src/wallet/hardware/trezor.ts
|
|
11154
|
-
var
|
|
13710
|
+
var import_types49 = require("@sip-protocol/types");
|
|
11155
13711
|
var TrezorWalletAdapter = class extends BaseWalletAdapter {
|
|
11156
13712
|
chain;
|
|
11157
13713
|
name = "trezor";
|
|
@@ -11297,7 +13853,7 @@ var TrezorWalletAdapter = class extends BaseWalletAdapter {
|
|
|
11297
13853
|
async getBalance() {
|
|
11298
13854
|
throw new WalletError(
|
|
11299
13855
|
"Hardware wallets do not track balances. Use an RPC provider.",
|
|
11300
|
-
|
|
13856
|
+
import_types49.WalletErrorCode.UNSUPPORTED_OPERATION
|
|
11301
13857
|
);
|
|
11302
13858
|
}
|
|
11303
13859
|
/**
|
|
@@ -11308,7 +13864,7 @@ var TrezorWalletAdapter = class extends BaseWalletAdapter {
|
|
|
11308
13864
|
async getTokenBalance(_asset) {
|
|
11309
13865
|
throw new WalletError(
|
|
11310
13866
|
"Hardware wallets do not track balances. Use an RPC provider.",
|
|
11311
|
-
|
|
13867
|
+
import_types49.WalletErrorCode.UNSUPPORTED_OPERATION
|
|
11312
13868
|
);
|
|
11313
13869
|
}
|
|
11314
13870
|
// ─── Account Management ─────────────────────────────────────────────────────
|
|
@@ -11589,8 +14145,8 @@ function createTrezorAdapter(config) {
|
|
|
11589
14145
|
}
|
|
11590
14146
|
|
|
11591
14147
|
// src/wallet/hardware/mock.ts
|
|
11592
|
-
var
|
|
11593
|
-
var
|
|
14148
|
+
var import_types51 = require("@sip-protocol/types");
|
|
14149
|
+
var import_utils26 = require("@noble/hashes/utils");
|
|
11594
14150
|
var MockLedgerAdapter = class extends BaseWalletAdapter {
|
|
11595
14151
|
chain;
|
|
11596
14152
|
name = "mock-ledger";
|
|
@@ -11737,7 +14293,7 @@ var MockLedgerAdapter = class extends BaseWalletAdapter {
|
|
|
11737
14293
|
async getBalance() {
|
|
11738
14294
|
throw new WalletError(
|
|
11739
14295
|
"Hardware wallets do not track balances",
|
|
11740
|
-
|
|
14296
|
+
import_types51.WalletErrorCode.UNSUPPORTED_OPERATION
|
|
11741
14297
|
);
|
|
11742
14298
|
}
|
|
11743
14299
|
/**
|
|
@@ -11746,7 +14302,7 @@ var MockLedgerAdapter = class extends BaseWalletAdapter {
|
|
|
11746
14302
|
async getTokenBalance(_asset) {
|
|
11747
14303
|
throw new WalletError(
|
|
11748
14304
|
"Hardware wallets do not track balances",
|
|
11749
|
-
|
|
14305
|
+
import_types51.WalletErrorCode.UNSUPPORTED_OPERATION
|
|
11750
14306
|
);
|
|
11751
14307
|
}
|
|
11752
14308
|
/**
|
|
@@ -11835,15 +14391,15 @@ var MockLedgerAdapter = class extends BaseWalletAdapter {
|
|
|
11835
14391
|
}
|
|
11836
14392
|
}
|
|
11837
14393
|
generateMockAddress(index) {
|
|
11838
|
-
const bytes = (0,
|
|
14394
|
+
const bytes = (0, import_utils26.randomBytes)(20);
|
|
11839
14395
|
bytes[0] = index;
|
|
11840
|
-
return `0x${(0,
|
|
14396
|
+
return `0x${(0, import_utils26.bytesToHex)(bytes)}`;
|
|
11841
14397
|
}
|
|
11842
14398
|
generateMockPublicKey(index) {
|
|
11843
|
-
const bytes = (0,
|
|
14399
|
+
const bytes = (0, import_utils26.randomBytes)(33);
|
|
11844
14400
|
bytes[0] = 2;
|
|
11845
14401
|
bytes[1] = index;
|
|
11846
|
-
return `0x${(0,
|
|
14402
|
+
return `0x${(0, import_utils26.bytesToHex)(bytes)}`;
|
|
11847
14403
|
}
|
|
11848
14404
|
generateMockSignature(data) {
|
|
11849
14405
|
const sig = new Uint8Array(65);
|
|
@@ -11852,7 +14408,7 @@ var MockLedgerAdapter = class extends BaseWalletAdapter {
|
|
|
11852
14408
|
sig[32 + i] = (data[i % data.length] ?? 0) ^ i * 11;
|
|
11853
14409
|
}
|
|
11854
14410
|
sig[64] = 27;
|
|
11855
|
-
return `0x${(0,
|
|
14411
|
+
return `0x${(0, import_utils26.bytesToHex)(sig)}`;
|
|
11856
14412
|
}
|
|
11857
14413
|
delay(ms) {
|
|
11858
14414
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -11976,13 +14532,13 @@ var MockTrezorAdapter = class extends BaseWalletAdapter {
|
|
|
11976
14532
|
async getBalance() {
|
|
11977
14533
|
throw new WalletError(
|
|
11978
14534
|
"Hardware wallets do not track balances",
|
|
11979
|
-
|
|
14535
|
+
import_types51.WalletErrorCode.UNSUPPORTED_OPERATION
|
|
11980
14536
|
);
|
|
11981
14537
|
}
|
|
11982
14538
|
async getTokenBalance(_asset) {
|
|
11983
14539
|
throw new WalletError(
|
|
11984
14540
|
"Hardware wallets do not track balances",
|
|
11985
|
-
|
|
14541
|
+
import_types51.WalletErrorCode.UNSUPPORTED_OPERATION
|
|
11986
14542
|
);
|
|
11987
14543
|
}
|
|
11988
14544
|
async getAccounts(startIndex = 0, count = 5) {
|
|
@@ -12041,15 +14597,15 @@ var MockTrezorAdapter = class extends BaseWalletAdapter {
|
|
|
12041
14597
|
}
|
|
12042
14598
|
}
|
|
12043
14599
|
generateMockAddress(index) {
|
|
12044
|
-
const bytes = (0,
|
|
14600
|
+
const bytes = (0, import_utils26.randomBytes)(20);
|
|
12045
14601
|
bytes[0] = index + 100;
|
|
12046
|
-
return `0x${(0,
|
|
14602
|
+
return `0x${(0, import_utils26.bytesToHex)(bytes)}`;
|
|
12047
14603
|
}
|
|
12048
14604
|
generateMockPublicKey(index) {
|
|
12049
|
-
const bytes = (0,
|
|
14605
|
+
const bytes = (0, import_utils26.randomBytes)(33);
|
|
12050
14606
|
bytes[0] = 3;
|
|
12051
14607
|
bytes[1] = index + 100;
|
|
12052
|
-
return `0x${(0,
|
|
14608
|
+
return `0x${(0, import_utils26.bytesToHex)(bytes)}`;
|
|
12053
14609
|
}
|
|
12054
14610
|
generateMockSignature(data) {
|
|
12055
14611
|
const sig = new Uint8Array(65);
|
|
@@ -12058,7 +14614,7 @@ var MockTrezorAdapter = class extends BaseWalletAdapter {
|
|
|
12058
14614
|
sig[32 + i] = (data[i % data.length] ?? 0) ^ i * 17;
|
|
12059
14615
|
}
|
|
12060
14616
|
sig[64] = 28;
|
|
12061
|
-
return `0x${(0,
|
|
14617
|
+
return `0x${(0, import_utils26.bytesToHex)(sig)}`;
|
|
12062
14618
|
}
|
|
12063
14619
|
delay(ms) {
|
|
12064
14620
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -12072,13 +14628,20 @@ function createMockTrezorAdapter(config) {
|
|
|
12072
14628
|
}
|
|
12073
14629
|
|
|
12074
14630
|
// src/wallet/index.ts
|
|
12075
|
-
var
|
|
14631
|
+
var import_types54 = require("@sip-protocol/types");
|
|
12076
14632
|
// Annotate the CommonJS export names for ESM import in node:
|
|
12077
14633
|
0 && (module.exports = {
|
|
12078
14634
|
ATTESTATION_VERSION,
|
|
14635
|
+
AptosStealthService,
|
|
14636
|
+
AuditorKeyDerivation,
|
|
14637
|
+
AuditorType,
|
|
12079
14638
|
BaseWalletAdapter,
|
|
12080
14639
|
CHAIN_NUMERIC_IDS,
|
|
14640
|
+
COSMOS_CHAIN_PREFIXES,
|
|
12081
14641
|
ComplianceManager,
|
|
14642
|
+
ComplianceReporter,
|
|
14643
|
+
ConditionalDisclosure,
|
|
14644
|
+
CosmosStealthService,
|
|
12082
14645
|
CryptoError,
|
|
12083
14646
|
DEFAULT_THRESHOLD,
|
|
12084
14647
|
DEFAULT_TOTAL_ORACLES,
|
|
@@ -12129,6 +14692,7 @@ var import_types36 = require("@sip-protocol/types");
|
|
|
12129
14692
|
SmartRouter,
|
|
12130
14693
|
SolanaWalletAdapter,
|
|
12131
14694
|
SwapStatus,
|
|
14695
|
+
ThresholdViewingKey,
|
|
12132
14696
|
Treasury,
|
|
12133
14697
|
TrezorWalletAdapter,
|
|
12134
14698
|
ValidationError,
|
|
@@ -12143,17 +14707,21 @@ var import_types36 = require("@sip-protocol/types");
|
|
|
12143
14707
|
addBlindings,
|
|
12144
14708
|
addCommitments,
|
|
12145
14709
|
addOracle,
|
|
14710
|
+
aptosAddressToAuthKey,
|
|
12146
14711
|
attachProofs,
|
|
12147
14712
|
base58ToHex,
|
|
12148
14713
|
browserBytesToHex,
|
|
12149
14714
|
browserHexToBytes,
|
|
14715
|
+
checkAptosStealthAddress,
|
|
12150
14716
|
checkEd25519StealthAddress,
|
|
12151
14717
|
checkStealthAddress,
|
|
12152
14718
|
commit,
|
|
12153
14719
|
commitZero,
|
|
12154
14720
|
computeAttestationHash,
|
|
14721
|
+
computeTweakedKey,
|
|
12155
14722
|
createCommitment,
|
|
12156
14723
|
createEthereumAdapter,
|
|
14724
|
+
createKeySpendOnlyOutput,
|
|
12157
14725
|
createLedgerAdapter,
|
|
12158
14726
|
createMockEthereumAdapter,
|
|
12159
14727
|
createMockEthereumProvider,
|
|
@@ -12172,6 +14740,7 @@ var import_types36 = require("@sip-protocol/types");
|
|
|
12172
14740
|
createShieldedPayment,
|
|
12173
14741
|
createSmartRouter,
|
|
12174
14742
|
createSolanaAdapter,
|
|
14743
|
+
createTaprootOutput,
|
|
12175
14744
|
createTrezorAdapter,
|
|
12176
14745
|
createWalletFactory,
|
|
12177
14746
|
createZcashClient,
|
|
@@ -12179,8 +14748,10 @@ var import_types36 = require("@sip-protocol/types");
|
|
|
12179
14748
|
createZcashShieldedService,
|
|
12180
14749
|
createZcashSwapService,
|
|
12181
14750
|
decodeStealthMetaAddress,
|
|
14751
|
+
decodeTaprootAddress,
|
|
12182
14752
|
decryptMemo,
|
|
12183
14753
|
decryptWithViewing,
|
|
14754
|
+
deriveAptosStealthPrivateKey,
|
|
12184
14755
|
deriveEd25519StealthPrivateKey,
|
|
12185
14756
|
deriveOracleId,
|
|
12186
14757
|
deriveStealthPrivateKey,
|
|
@@ -12190,6 +14761,7 @@ var import_types36 = require("@sip-protocol/types");
|
|
|
12190
14761
|
deserializePayment,
|
|
12191
14762
|
detectEthereumWallets,
|
|
12192
14763
|
detectSolanaWallets,
|
|
14764
|
+
ed25519PublicKeyToAptosAddress,
|
|
12193
14765
|
ed25519PublicKeyToNearAddress,
|
|
12194
14766
|
ed25519PublicKeyToSolanaAddress,
|
|
12195
14767
|
encodeStealthMetaAddress,
|
|
@@ -12198,10 +14770,14 @@ var import_types36 = require("@sip-protocol/types");
|
|
|
12198
14770
|
formatStablecoinAmount,
|
|
12199
14771
|
fromHex,
|
|
12200
14772
|
fromStablecoinUnits,
|
|
14773
|
+
generateAptosStealthAddress,
|
|
12201
14774
|
generateBlinding,
|
|
14775
|
+
generateCosmosStealthAddress,
|
|
14776
|
+
generateCosmosStealthMetaAddress,
|
|
12202
14777
|
generateEd25519StealthAddress,
|
|
12203
14778
|
generateEd25519StealthMetaAddress,
|
|
12204
14779
|
generateIntentId,
|
|
14780
|
+
generatePdfReport,
|
|
12205
14781
|
generateRandomBytes,
|
|
12206
14782
|
generateStealthAddress,
|
|
12207
14783
|
generateStealthMetaAddress,
|
|
@@ -12228,6 +14804,7 @@ var import_types36 = require("@sip-protocol/types");
|
|
|
12228
14804
|
getStablecoinsForChain,
|
|
12229
14805
|
getSupportedStablecoins,
|
|
12230
14806
|
getTimeRemaining,
|
|
14807
|
+
getXOnlyPublicKey,
|
|
12231
14808
|
hasEnoughOracles,
|
|
12232
14809
|
hasErrorCode,
|
|
12233
14810
|
hasRequiredProofs,
|
|
@@ -12244,8 +14821,10 @@ var import_types36 = require("@sip-protocol/types");
|
|
|
12244
14821
|
isStablecoin,
|
|
12245
14822
|
isStablecoinOnChain,
|
|
12246
14823
|
isValidAmount,
|
|
14824
|
+
isValidAptosAddress,
|
|
12247
14825
|
isValidChainId,
|
|
12248
14826
|
isValidCompressedPublicKey,
|
|
14827
|
+
isValidCosmosAddress,
|
|
12249
14828
|
isValidEd25519PublicKey,
|
|
12250
14829
|
isValidHex,
|
|
12251
14830
|
isValidHexLength,
|
|
@@ -12257,12 +14836,17 @@ var import_types36 = require("@sip-protocol/types");
|
|
|
12257
14836
|
isValidSlippage,
|
|
12258
14837
|
isValidSolanaAddress,
|
|
12259
14838
|
isValidStealthMetaAddress,
|
|
14839
|
+
isValidTaprootAddress,
|
|
12260
14840
|
nearAddressToEd25519PublicKey,
|
|
12261
14841
|
normalizeAddress,
|
|
12262
14842
|
notConnectedError,
|
|
12263
14843
|
publicKeyToEthAddress,
|
|
12264
14844
|
registerWallet,
|
|
12265
14845
|
removeOracle,
|
|
14846
|
+
schnorrSign,
|
|
14847
|
+
schnorrSignHex,
|
|
14848
|
+
schnorrVerify,
|
|
14849
|
+
schnorrVerifyHex,
|
|
12266
14850
|
secureWipe,
|
|
12267
14851
|
secureWipeAll,
|
|
12268
14852
|
serializeAttestationMessage,
|
|
@@ -12271,6 +14855,7 @@ var import_types36 = require("@sip-protocol/types");
|
|
|
12271
14855
|
signAttestationMessage,
|
|
12272
14856
|
solanaAddressToEd25519PublicKey,
|
|
12273
14857
|
solanaPublicKeyToHex,
|
|
14858
|
+
stealthKeyToCosmosAddress,
|
|
12274
14859
|
subtractBlindings,
|
|
12275
14860
|
subtractCommitments,
|
|
12276
14861
|
supportsSharedArrayBuffer,
|
|
@@ -12279,6 +14864,7 @@ var import_types36 = require("@sip-protocol/types");
|
|
|
12279
14864
|
supportsWebHID,
|
|
12280
14865
|
supportsWebUSB,
|
|
12281
14866
|
supportsWebWorkers,
|
|
14867
|
+
taprootAddress,
|
|
12282
14868
|
toHex,
|
|
12283
14869
|
toStablecoinUnits,
|
|
12284
14870
|
trackIntent,
|