@sip-protocol/sdk 0.2.10 → 0.3.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.
Files changed (43) hide show
  1. package/dist/browser.d.mts +1 -1
  2. package/dist/browser.d.ts +1 -1
  3. package/dist/browser.js +1334 -199
  4. package/dist/browser.mjs +19 -1
  5. package/dist/chunk-4IFOPYJF.mjs +11950 -0
  6. package/dist/chunk-4VJHI66K.mjs +12120 -0
  7. package/dist/chunk-5BAS4D44.mjs +10283 -0
  8. package/dist/chunk-6WOV2YNG.mjs +10179 -0
  9. package/dist/chunk-7IMRM7LN.mjs +12149 -0
  10. package/dist/chunk-DU7LQDD2.mjs +10148 -0
  11. package/dist/{chunk-AV37IZST.mjs → chunk-JNNXNTSS.mjs} +14 -0
  12. package/dist/chunk-KXN6IWL5.mjs +10736 -0
  13. package/dist/chunk-MR7HRCRS.mjs +10165 -0
  14. package/dist/chunk-NDGUWOOZ.mjs +10157 -0
  15. package/dist/chunk-O4Y2ZUDL.mjs +12721 -0
  16. package/dist/chunk-UPTISVCY.mjs +10304 -0
  17. package/dist/chunk-VITVG25F.mjs +982 -0
  18. package/dist/chunk-VXSHK7US.mjs +10158 -0
  19. package/dist/chunk-W3YXIQ7L.mjs +11950 -0
  20. package/dist/index-Ba7njCU3.d.ts +6925 -0
  21. package/dist/index-Co26-vbG.d.mts +6925 -0
  22. package/dist/{index-CAhjA4kh.d.mts → index-DqZoHYKI.d.mts} +362 -6
  23. package/dist/index-dTtK_DTl.d.ts +6762 -0
  24. package/dist/index-jnkYu-Z4.d.mts +6762 -0
  25. package/dist/{index-BFOKTz2z.d.ts → index-vB1N1mHd.d.ts} +362 -6
  26. package/dist/index.d.mts +1 -1
  27. package/dist/index.d.ts +1 -1
  28. package/dist/index.js +1334 -199
  29. package/dist/index.mjs +19 -1
  30. package/dist/noir-BHQtFvRk.d.mts +467 -0
  31. package/dist/noir-BHQtFvRk.d.ts +467 -0
  32. package/package.json +14 -14
  33. package/src/index.ts +32 -0
  34. package/src/settlement/README.md +439 -0
  35. package/src/settlement/backends/direct-chain.ts +569 -0
  36. package/src/settlement/backends/index.ts +22 -0
  37. package/src/settlement/backends/near-intents.ts +480 -0
  38. package/src/settlement/backends/zcash-native.ts +516 -0
  39. package/src/settlement/index.ts +47 -0
  40. package/src/settlement/interface.ts +397 -0
  41. package/src/settlement/registry.ts +269 -0
  42. package/src/settlement/router.ts +383 -0
  43. package/LICENSE +0 -21
@@ -0,0 +1,516 @@
1
+ /**
2
+ * Zcash Native Settlement Backend
3
+ *
4
+ * Settlement backend for direct Zcash-to-Zcash transactions.
5
+ * Uses ZcashSwapService for shielded transfers within the Zcash network.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * const backend = new ZcashNativeBackend({
10
+ * swapService: zcashSwapService,
11
+ * })
12
+ *
13
+ * const quote = await backend.getQuote({
14
+ * fromChain: 'zcash',
15
+ * toChain: 'zcash',
16
+ * fromToken: 'ZEC',
17
+ * toToken: 'ZEC',
18
+ * amount: 100000000n, // 1 ZEC
19
+ * privacyLevel: PrivacyLevel.SHIELDED,
20
+ * })
21
+ * ```
22
+ */
23
+
24
+ import { PrivacyLevel, type ChainId } from '@sip-protocol/types'
25
+ import {
26
+ type SettlementBackend,
27
+ type QuoteParams,
28
+ type Quote,
29
+ type SwapParams,
30
+ type SwapResult,
31
+ type SwapStatusResponse,
32
+ type BackendCapabilities,
33
+ SwapStatus,
34
+ } from '../interface'
35
+ import { ValidationError, ErrorCode } from '../../errors'
36
+ import type { ZcashSwapService } from '../../zcash'
37
+
38
+ // ─── Configuration Types ───────────────────────────────────────────────────
39
+
40
+ /**
41
+ * Configuration for ZcashNativeBackend
42
+ */
43
+ export interface ZcashNativeBackendConfig {
44
+ /** Zcash swap service instance */
45
+ swapService: ZcashSwapService
46
+ /** Default quote validity in seconds (default: 300 = 5 minutes) */
47
+ quoteValiditySeconds?: number
48
+ /** Network fee estimate in zatoshis (default: 10000 = 0.0001 ZEC) */
49
+ networkFeeZatoshis?: number
50
+ }
51
+
52
+ // ─── Backend Implementation ────────────────────────────────────────────────
53
+
54
+ /**
55
+ * Zcash Native Settlement Backend
56
+ *
57
+ * Handles ZEC → ZEC transfers within the Zcash network.
58
+ * Supports both transparent (t-addr) and shielded (z-addr) addresses.
59
+ */
60
+ export class ZcashNativeBackend implements SettlementBackend {
61
+ readonly name = 'zcash-native' as const
62
+ readonly capabilities: BackendCapabilities
63
+
64
+ private readonly swapService: ZcashSwapService
65
+ private readonly config: Required<Omit<ZcashNativeBackendConfig, 'swapService'>>
66
+ private readonly quotes = new Map<string, Quote>()
67
+ private readonly swaps = new Map<string, SwapResult>()
68
+
69
+ constructor(config: ZcashNativeBackendConfig) {
70
+ this.swapService = config.swapService
71
+ this.config = {
72
+ quoteValiditySeconds: config.quoteValiditySeconds ?? 300,
73
+ networkFeeZatoshis: config.networkFeeZatoshis ?? 10000,
74
+ }
75
+
76
+ this.capabilities = {
77
+ supportedSourceChains: ['zcash'],
78
+ supportedDestinationChains: ['zcash'],
79
+ supportedPrivacyLevels: [
80
+ PrivacyLevel.TRANSPARENT,
81
+ PrivacyLevel.SHIELDED,
82
+ PrivacyLevel.COMPLIANT,
83
+ ],
84
+ supportsCancellation: false,
85
+ supportsRefunds: false,
86
+ averageExecutionTime: 75, // ~75 seconds for Zcash block confirmation
87
+ features: [
88
+ 'native-zcash',
89
+ 'shielded-addresses',
90
+ 'transparent-addresses',
91
+ 'instant-quotes',
92
+ ],
93
+ }
94
+ }
95
+
96
+ // ─── Quote Methods ─────────────────────────────────────────────────────────
97
+
98
+ /**
99
+ * Get a quote for ZEC → ZEC transfer
100
+ */
101
+ async getQuote(params: QuoteParams): Promise<Quote> {
102
+ this.validateQuoteParams(params)
103
+
104
+ const { amount, recipientMetaAddress, senderAddress, privacyLevel } = params
105
+
106
+ // Generate quote ID
107
+ const quoteId = this.generateQuoteId()
108
+ const now = Math.floor(Date.now() / 1000)
109
+ const expiresAt = now + this.config.quoteValiditySeconds
110
+
111
+ // Calculate fees (simple network fee for ZEC transfers)
112
+ const networkFee = BigInt(this.config.networkFeeZatoshis)
113
+ const protocolFee = BigInt(0) // No protocol fee for native transfers
114
+ const totalFee = networkFee
115
+
116
+ // Calculate output amount (input - fees)
117
+ const amountOut = amount - totalFee
118
+ if (amountOut <= BigInt(0)) {
119
+ throw new ValidationError(
120
+ 'Amount too small to cover network fees',
121
+ 'amount',
122
+ { amount: amount.toString(), networkFee: networkFee.toString() },
123
+ ErrorCode.INVALID_AMOUNT,
124
+ )
125
+ }
126
+
127
+ // Minimum output (99% of expected, accounting for potential fee variations)
128
+ const minAmountOut = (amountOut * BigInt(99)) / BigInt(100)
129
+
130
+ // Generate deposit address based on privacy level
131
+ let depositAddress: string
132
+ let recipientAddress: string
133
+
134
+ if (privacyLevel === PrivacyLevel.SHIELDED || privacyLevel === PrivacyLevel.COMPLIANT) {
135
+ // For shielded transfers, we need z-addresses
136
+ if (typeof recipientMetaAddress === 'string') {
137
+ // Assume it's a z-address
138
+ recipientAddress = recipientMetaAddress
139
+ } else if (recipientMetaAddress) {
140
+ // Generate stealth address from meta-address (simplified for now)
141
+ recipientAddress = `zs1${this.randomHex(72)}` // Mock z-address
142
+ } else {
143
+ throw new ValidationError(
144
+ 'Recipient address required for shielded transfers',
145
+ 'recipientMetaAddress',
146
+ undefined,
147
+ ErrorCode.VALIDATION_FAILED,
148
+ )
149
+ }
150
+
151
+ // Generate a z-address for deposit
152
+ depositAddress = `zs1${this.randomHex(72)}`
153
+ } else {
154
+ // Transparent transfer
155
+ if (senderAddress) {
156
+ depositAddress = senderAddress
157
+ } else {
158
+ depositAddress = `t1${this.randomBase58(33)}` // Mock t-address
159
+ }
160
+
161
+ if (typeof recipientMetaAddress === 'string') {
162
+ recipientAddress = recipientMetaAddress
163
+ } else {
164
+ throw new ValidationError(
165
+ 'Recipient address required',
166
+ 'recipientMetaAddress',
167
+ undefined,
168
+ ErrorCode.VALIDATION_FAILED,
169
+ )
170
+ }
171
+ }
172
+
173
+ const quote: Quote = {
174
+ quoteId,
175
+ amountIn: amount.toString(),
176
+ amountOut: amountOut.toString(),
177
+ minAmountOut: minAmountOut.toString(),
178
+ fees: {
179
+ networkFee: networkFee.toString(),
180
+ protocolFee: protocolFee.toString(),
181
+ },
182
+ depositAddress,
183
+ recipientAddress,
184
+ expiresAt,
185
+ estimatedTime: this.capabilities.averageExecutionTime,
186
+ metadata: {
187
+ backend: this.name,
188
+ privacyLevel,
189
+ zcashNetwork: 'mainnet',
190
+ },
191
+ }
192
+
193
+ // Store quote
194
+ this.quotes.set(quoteId, quote)
195
+
196
+ return quote
197
+ }
198
+
199
+ /**
200
+ * Get a dry quote (preview without creating deposit address)
201
+ */
202
+ async getDryQuote(params: QuoteParams): Promise<Quote> {
203
+ // For Zcash native, dry quote is the same as regular quote
204
+ // since we don't need to reserve resources
205
+ return this.getQuote(params)
206
+ }
207
+
208
+ // ─── Swap Execution ────────────────────────────────────────────────────────
209
+
210
+ /**
211
+ * Execute a ZEC → ZEC swap/transfer
212
+ */
213
+ async executeSwap(params: SwapParams): Promise<SwapResult> {
214
+ const { quoteId, depositTxHash } = params
215
+
216
+ // Retrieve quote
217
+ const quote = this.quotes.get(quoteId)
218
+ if (!quote) {
219
+ throw new ValidationError(
220
+ 'Quote not found or expired',
221
+ 'quoteId',
222
+ { quoteId },
223
+ ErrorCode.VALIDATION_FAILED,
224
+ )
225
+ }
226
+
227
+ // Check expiration
228
+ const now = Math.floor(Date.now() / 1000)
229
+ if (now > quote.expiresAt) {
230
+ throw new ValidationError(
231
+ 'Quote has expired',
232
+ 'quoteId',
233
+ { quoteId, expiresAt: quote.expiresAt, now },
234
+ ErrorCode.VALIDATION_FAILED,
235
+ )
236
+ }
237
+
238
+ // Generate swap ID
239
+ const swapId = this.generateSwapId()
240
+
241
+ // Create swap result
242
+ const result: SwapResult = {
243
+ swapId,
244
+ status: depositTxHash ? SwapStatus.DEPOSIT_CONFIRMED : SwapStatus.PENDING_DEPOSIT,
245
+ quoteId,
246
+ depositAddress: quote.depositAddress,
247
+ depositTxHash,
248
+ metadata: {
249
+ backend: this.name,
250
+ recipientAddress: quote.recipientAddress,
251
+ },
252
+ }
253
+
254
+ // Store swap
255
+ this.swaps.set(swapId, result)
256
+
257
+ // If deposit TX is provided, simulate processing
258
+ if (depositTxHash) {
259
+ // In a real implementation, we would:
260
+ // 1. Verify the deposit transaction on Zcash blockchain
261
+ // 2. Wait for confirmations
262
+ // 3. Execute the transfer to recipient
263
+ // For now, we'll simulate immediate success
264
+ this.simulateSwapExecution(swapId, quote)
265
+ }
266
+
267
+ return result
268
+ }
269
+
270
+ // ─── Status Methods ────────────────────────────────────────────────────────
271
+
272
+ /**
273
+ * Get swap status
274
+ */
275
+ async getStatus(swapId: string): Promise<SwapStatusResponse> {
276
+ const swap = this.swaps.get(swapId)
277
+ if (!swap) {
278
+ throw new ValidationError(
279
+ 'Swap not found',
280
+ 'swapId',
281
+ { swapId },
282
+ ErrorCode.VALIDATION_FAILED,
283
+ )
284
+ }
285
+
286
+ const quote = this.quotes.get(swap.quoteId)
287
+ if (!quote) {
288
+ throw new ValidationError(
289
+ 'Quote not found for swap',
290
+ 'quoteId',
291
+ { quoteId: swap.quoteId },
292
+ ErrorCode.VALIDATION_FAILED,
293
+ )
294
+ }
295
+
296
+ const status: SwapStatusResponse = {
297
+ swapId: swap.swapId,
298
+ status: swap.status,
299
+ quoteId: swap.quoteId,
300
+ depositAddress: swap.depositAddress,
301
+ amountIn: quote.amountIn,
302
+ amountOut: quote.amountOut,
303
+ depositTxHash: swap.depositTxHash,
304
+ settlementTxHash: swap.settlementTxHash,
305
+ actualAmountOut: swap.actualAmountOut,
306
+ errorMessage: swap.errorMessage,
307
+ updatedAt: Math.floor(Date.now() / 1000),
308
+ metadata: swap.metadata,
309
+ }
310
+
311
+ return status
312
+ }
313
+
314
+ /**
315
+ * Wait for swap completion
316
+ */
317
+ async waitForCompletion(
318
+ swapId: string,
319
+ options?: {
320
+ interval?: number
321
+ timeout?: number
322
+ onStatusChange?: (status: SwapStatusResponse) => void
323
+ },
324
+ ): Promise<SwapStatusResponse> {
325
+ const interval = options?.interval ?? 5000
326
+ const timeout = options?.timeout ?? 600000 // 10 minutes default
327
+ const startTime = Date.now()
328
+
329
+ while (Date.now() - startTime < timeout) {
330
+ const status = await this.getStatus(swapId)
331
+
332
+ // Notify callback
333
+ if (options?.onStatusChange) {
334
+ options.onStatusChange(status)
335
+ }
336
+
337
+ // Check terminal states
338
+ if (status.status === SwapStatus.SUCCESS) {
339
+ return status
340
+ }
341
+
342
+ if (
343
+ status.status === SwapStatus.FAILED ||
344
+ status.status === SwapStatus.CANCELLED ||
345
+ status.status === SwapStatus.REFUNDED
346
+ ) {
347
+ return status
348
+ }
349
+
350
+ // Wait before next poll
351
+ await this.delay(interval)
352
+ }
353
+
354
+ // Timeout reached
355
+ const status = await this.getStatus(swapId)
356
+ return status
357
+ }
358
+
359
+ /**
360
+ * Notify backend of deposit
361
+ */
362
+ async notifyDeposit(
363
+ swapId: string,
364
+ txHash: string,
365
+ metadata?: Record<string, unknown>,
366
+ ): Promise<void> {
367
+ const swap = this.swaps.get(swapId)
368
+ if (!swap) {
369
+ throw new ValidationError(
370
+ 'Swap not found',
371
+ 'swapId',
372
+ { swapId },
373
+ ErrorCode.VALIDATION_FAILED,
374
+ )
375
+ }
376
+
377
+ // Update swap with deposit info
378
+ swap.depositTxHash = txHash
379
+ swap.status = SwapStatus.DEPOSIT_CONFIRMED
380
+ if (metadata) {
381
+ swap.metadata = { ...swap.metadata, ...metadata }
382
+ }
383
+
384
+ this.swaps.set(swapId, swap)
385
+
386
+ // Trigger swap execution
387
+ const quote = this.quotes.get(swap.quoteId)
388
+ if (quote) {
389
+ this.simulateSwapExecution(swapId, quote)
390
+ }
391
+ }
392
+
393
+ // ─── Private Helpers ───────────────────────────────────────────────────────
394
+
395
+ private validateQuoteParams(params: QuoteParams): void {
396
+ // Validate chains
397
+ if (params.fromChain !== 'zcash') {
398
+ throw new ValidationError(
399
+ 'Source chain must be zcash',
400
+ 'fromChain',
401
+ { received: params.fromChain, expected: 'zcash' },
402
+ ErrorCode.VALIDATION_FAILED,
403
+ )
404
+ }
405
+
406
+ if (params.toChain !== 'zcash') {
407
+ throw new ValidationError(
408
+ 'Destination chain must be zcash',
409
+ 'toChain',
410
+ { received: params.toChain, expected: 'zcash' },
411
+ ErrorCode.VALIDATION_FAILED,
412
+ )
413
+ }
414
+
415
+ // Validate tokens
416
+ if (params.fromToken !== 'ZEC') {
417
+ throw new ValidationError(
418
+ 'Source token must be ZEC',
419
+ 'fromToken',
420
+ { received: params.fromToken, expected: 'ZEC' },
421
+ ErrorCode.VALIDATION_FAILED,
422
+ )
423
+ }
424
+
425
+ if (params.toToken !== 'ZEC') {
426
+ throw new ValidationError(
427
+ 'Destination token must be ZEC',
428
+ 'toToken',
429
+ { received: params.toToken, expected: 'ZEC' },
430
+ ErrorCode.VALIDATION_FAILED,
431
+ )
432
+ }
433
+
434
+ // Validate amount
435
+ if (!params.amount || params.amount <= BigInt(0)) {
436
+ throw new ValidationError(
437
+ 'Amount must be positive',
438
+ 'amount',
439
+ { received: params.amount },
440
+ ErrorCode.INVALID_AMOUNT,
441
+ )
442
+ }
443
+
444
+ // Validate privacy level
445
+ if (!this.capabilities.supportedPrivacyLevels.includes(params.privacyLevel)) {
446
+ throw new ValidationError(
447
+ 'Unsupported privacy level',
448
+ 'privacyLevel',
449
+ { received: params.privacyLevel, supported: this.capabilities.supportedPrivacyLevels },
450
+ ErrorCode.VALIDATION_FAILED,
451
+ )
452
+ }
453
+ }
454
+
455
+ private simulateSwapExecution(swapId: string, quote: Quote): void {
456
+ // Simulate async execution
457
+ setTimeout(() => {
458
+ const swap = this.swaps.get(swapId)
459
+ if (!swap) return
460
+
461
+ // Update to in progress
462
+ swap.status = SwapStatus.IN_PROGRESS
463
+ this.swaps.set(swapId, swap)
464
+
465
+ // Simulate completion after delay
466
+ setTimeout(() => {
467
+ const finalSwap = this.swaps.get(swapId)
468
+ if (!finalSwap) return
469
+
470
+ finalSwap.status = SwapStatus.SUCCESS
471
+ finalSwap.settlementTxHash = this.randomHex(64)
472
+ finalSwap.actualAmountOut = quote.amountOut
473
+ this.swaps.set(swapId, finalSwap)
474
+ }, 2000)
475
+ }, 1000)
476
+ }
477
+
478
+ private generateQuoteId(): string {
479
+ return `zec_native_quote_${Date.now()}_${this.randomHex(8)}`
480
+ }
481
+
482
+ private generateSwapId(): string {
483
+ return `zec_native_swap_${Date.now()}_${this.randomHex(8)}`
484
+ }
485
+
486
+ private randomHex(length: number): string {
487
+ const chars = '0123456789abcdef'
488
+ let result = ''
489
+ for (let i = 0; i < length; i++) {
490
+ result += chars[Math.floor(Math.random() * chars.length)]
491
+ }
492
+ return result
493
+ }
494
+
495
+ private randomBase58(length: number): string {
496
+ const chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
497
+ let result = ''
498
+ for (let i = 0; i < length; i++) {
499
+ result += chars[Math.floor(Math.random() * chars.length)]
500
+ }
501
+ return result
502
+ }
503
+
504
+ private delay(ms: number): Promise<void> {
505
+ return new Promise((resolve) => setTimeout(resolve, ms))
506
+ }
507
+ }
508
+
509
+ /**
510
+ * Create a Zcash Native backend instance
511
+ */
512
+ export function createZcashNativeBackend(
513
+ config: ZcashNativeBackendConfig,
514
+ ): ZcashNativeBackend {
515
+ return new ZcashNativeBackend(config)
516
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Settlement Backend Abstraction Layer
3
+ *
4
+ * Provides a unified interface for multiple settlement backends (NEAR Intents, Zcash, THORChain, etc.)
5
+ *
6
+ * @module settlement
7
+ */
8
+
9
+ export {
10
+ SwapStatus,
11
+ type SettlementBackendName,
12
+ type QuoteParams,
13
+ type Quote,
14
+ type SwapRoute,
15
+ type SwapRouteStep,
16
+ type SwapParams,
17
+ type SwapResult,
18
+ type SwapStatusResponse,
19
+ type BackendCapabilities,
20
+ type SettlementBackend,
21
+ type SettlementBackendFactory,
22
+ type SettlementBackendRegistry,
23
+ } from './interface'
24
+
25
+ export {
26
+ SettlementRegistry,
27
+ SettlementRegistryError,
28
+ type Route,
29
+ } from './registry'
30
+
31
+ // Router
32
+ export {
33
+ SmartRouter,
34
+ createSmartRouter,
35
+ type RouteWithQuote,
36
+ type QuoteComparison,
37
+ type FindBestRouteParams,
38
+ } from './router'
39
+
40
+ // Backends
41
+ export {
42
+ NEARIntentsBackend,
43
+ createNEARIntentsBackend,
44
+ ZcashNativeBackend,
45
+ createZcashNativeBackend,
46
+ type ZcashNativeBackendConfig,
47
+ } from './backends'