@sip-protocol/sdk 0.2.9 → 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 (42) hide show
  1. package/dist/browser.d.mts +100 -2
  2. package/dist/browser.d.ts +100 -2
  3. package/dist/browser.js +2116 -321
  4. package/dist/browser.mjs +516 -16
  5. package/dist/chunk-4IFOPYJF.mjs +11950 -0
  6. package/dist/chunk-7IMRM7LN.mjs +12149 -0
  7. package/dist/chunk-JNNXNTSS.mjs +11034 -0
  8. package/dist/chunk-W3YXIQ7L.mjs +11950 -0
  9. package/dist/chunk-XLEPIR2P.mjs +884 -0
  10. package/dist/index-Ba7njCU3.d.ts +6925 -0
  11. package/dist/index-Co26-vbG.d.mts +6925 -0
  12. package/dist/index-DqZoHYKI.d.mts +6418 -0
  13. package/dist/index-dTtK_DTl.d.ts +6762 -0
  14. package/dist/index-jnkYu-Z4.d.mts +6762 -0
  15. package/dist/index-vB1N1mHd.d.ts +6418 -0
  16. package/dist/index.d.mts +2 -5897
  17. package/dist/index.d.ts +2 -5897
  18. package/dist/index.js +1334 -199
  19. package/dist/index.mjs +19 -1
  20. package/dist/noir-BTyLXLlZ.d.mts +467 -0
  21. package/dist/noir-BTyLXLlZ.d.ts +467 -0
  22. package/dist/proofs/noir.d.mts +1 -1
  23. package/dist/proofs/noir.d.ts +1 -1
  24. package/dist/proofs/noir.js +11 -112
  25. package/dist/proofs/noir.mjs +10 -13
  26. package/package.json +3 -3
  27. package/src/browser.ts +23 -0
  28. package/src/index.ts +32 -0
  29. package/src/proofs/browser-utils.ts +389 -0
  30. package/src/proofs/browser.ts +246 -19
  31. package/src/proofs/circuits/funding_proof.json +1 -1
  32. package/src/proofs/noir.ts +14 -14
  33. package/src/proofs/worker.ts +426 -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
@@ -0,0 +1,439 @@
1
+ # Settlement Backend Interface
2
+
3
+ This directory contains the settlement abstraction layer for SIP Protocol, enabling pluggable settlement backends for cross-chain swaps.
4
+
5
+ ## Overview
6
+
7
+ The `SettlementBackend` interface provides a unified API for executing cross-chain swaps through different settlement providers (NEAR Intents, Zcash, THORChain, direct on-chain execution, etc.).
8
+
9
+ ## Architecture
10
+
11
+ ```
12
+ ┌─────────────────────────────────────────────────────────┐
13
+ │ SIP SDK (Application Layer) │
14
+ │ • createIntent() │
15
+ │ • getQuotes() │
16
+ │ • execute() │
17
+ └────────────────────┬────────────────────────────────────┘
18
+
19
+
20
+ ┌─────────────────────────────────────────────────────────┐
21
+ │ Settlement Backend Interface (Abstraction Layer) │
22
+ │ • getQuote() │
23
+ │ • executeSwap() │
24
+ │ • getStatus() │
25
+ └────────────────────┬────────────────────────────────────┘
26
+
27
+ ┌───────────┼───────────┬───────────────┐
28
+ ▼ ▼ ▼ ▼
29
+ ┌─────────────┐ ┌─────────┐ ┌──────────┐ ┌──────────────┐
30
+ │ NEAR │ │ Zcash │ │THORChain │ │ Direct Chain │
31
+ │ Intents │ │ Backend │ │ Backend │ │ Backend │
32
+ └─────────────┘ └─────────┘ └──────────┘ └──────────────┘
33
+ ```
34
+
35
+ ## Core Types
36
+
37
+ ### SettlementBackend
38
+
39
+ The main interface that all backends must implement:
40
+
41
+ ```typescript
42
+ interface SettlementBackend {
43
+ readonly name: SettlementBackendName
44
+ readonly capabilities: BackendCapabilities
45
+
46
+ getQuote(params: QuoteParams): Promise<Quote>
47
+ executeSwap(params: SwapParams): Promise<SwapResult>
48
+ getStatus(swapId: string): Promise<SwapStatusResponse>
49
+
50
+ // Optional methods
51
+ cancel?(swapId: string): Promise<void>
52
+ waitForCompletion?(swapId: string, options?): Promise<SwapStatusResponse>
53
+ getDryQuote?(params: QuoteParams): Promise<Quote>
54
+ notifyDeposit?(swapId: string, txHash: string, metadata?): Promise<void>
55
+ }
56
+ ```
57
+
58
+ ### QuoteParams
59
+
60
+ Parameters for requesting a swap quote:
61
+
62
+ ```typescript
63
+ interface QuoteParams {
64
+ fromChain: ChainId
65
+ toChain: ChainId
66
+ fromToken: string
67
+ toToken: string
68
+ amount: bigint
69
+ privacyLevel: PrivacyLevel
70
+ recipientMetaAddress?: StealthMetaAddress | string
71
+ senderAddress?: string
72
+ slippageTolerance?: number
73
+ deadline?: number
74
+ }
75
+ ```
76
+
77
+ ### Quote
78
+
79
+ Quote response with pricing and execution details:
80
+
81
+ ```typescript
82
+ interface Quote {
83
+ quoteId: string
84
+ amountIn: string
85
+ amountOut: string
86
+ minAmountOut: string
87
+ fees: {
88
+ networkFee: string
89
+ protocolFee: string
90
+ totalFeeUSD?: string
91
+ }
92
+ depositAddress: string
93
+ recipientAddress: string
94
+ expiresAt: number
95
+ // ... optional fields
96
+ }
97
+ ```
98
+
99
+ ### SwapStatus
100
+
101
+ Enum tracking swap lifecycle:
102
+
103
+ ```typescript
104
+ enum SwapStatus {
105
+ PENDING_DEPOSIT = 'pending_deposit',
106
+ DEPOSIT_CONFIRMED = 'deposit_confirmed',
107
+ IN_PROGRESS = 'in_progress',
108
+ SUCCESS = 'success',
109
+ FAILED = 'failed',
110
+ CANCELLED = 'cancelled',
111
+ REFUNDING = 'refunding',
112
+ REFUNDED = 'refunded',
113
+ }
114
+ ```
115
+
116
+ ## Implementing a Backend
117
+
118
+ ### 1. Basic Implementation
119
+
120
+ ```typescript
121
+ import type {
122
+ SettlementBackend,
123
+ QuoteParams,
124
+ Quote,
125
+ SwapParams,
126
+ SwapResult,
127
+ SwapStatusResponse,
128
+ BackendCapabilities,
129
+ } from '@sip-protocol/sdk'
130
+
131
+ export class MySettlementBackend implements SettlementBackend {
132
+ readonly name = 'my-backend'
133
+ readonly capabilities: BackendCapabilities = {
134
+ supportedSourceChains: ['ethereum', 'solana'],
135
+ supportedDestinationChains: ['near', 'polygon'],
136
+ supportedPrivacyLevels: [PrivacyLevel.TRANSPARENT, PrivacyLevel.SHIELDED],
137
+ supportsCancellation: false,
138
+ supportsRefunds: true,
139
+ averageExecutionTime: 120, // seconds
140
+ }
141
+
142
+ constructor(private config: MyBackendConfig) {}
143
+
144
+ async getQuote(params: QuoteParams): Promise<Quote> {
145
+ // 1. Validate parameters
146
+ this.validateQuoteParams(params)
147
+
148
+ // 2. Call backend API for quote
149
+ const backendQuote = await this.fetchQuote(params)
150
+
151
+ // 3. Convert to standard Quote format
152
+ return {
153
+ quoteId: backendQuote.id,
154
+ amountIn: params.amount.toString(),
155
+ amountOut: backendQuote.outputAmount,
156
+ minAmountOut: this.calculateMinOutput(
157
+ backendQuote.outputAmount,
158
+ params.slippageTolerance
159
+ ),
160
+ fees: {
161
+ networkFee: backendQuote.networkFee,
162
+ protocolFee: backendQuote.protocolFee,
163
+ },
164
+ depositAddress: backendQuote.depositAddress,
165
+ recipientAddress: backendQuote.recipient,
166
+ expiresAt: Date.now() + 300000, // 5 minutes
167
+ }
168
+ }
169
+
170
+ async executeSwap(params: SwapParams): Promise<SwapResult> {
171
+ // 1. Retrieve quote
172
+ const quote = await this.getQuoteById(params.quoteId)
173
+
174
+ // 2. Execute swap (may involve signing, approvals, etc.)
175
+ const execution = await this.executeBackendSwap(params)
176
+
177
+ // 3. Return result
178
+ return {
179
+ swapId: execution.id,
180
+ status: SwapStatus.PENDING_DEPOSIT,
181
+ quoteId: params.quoteId,
182
+ depositAddress: execution.depositAddress,
183
+ }
184
+ }
185
+
186
+ async getStatus(swapId: string): Promise<SwapStatusResponse> {
187
+ // Query backend for current status
188
+ const backendStatus = await this.fetchStatus(swapId)
189
+
190
+ return {
191
+ swapId,
192
+ status: this.mapStatus(backendStatus.status),
193
+ quoteId: backendStatus.quoteId,
194
+ depositAddress: backendStatus.depositAddress,
195
+ amountIn: backendStatus.amountIn,
196
+ amountOut: backendStatus.amountOut,
197
+ depositTxHash: backendStatus.depositTx,
198
+ settlementTxHash: backendStatus.settlementTx,
199
+ updatedAt: backendStatus.lastUpdated,
200
+ }
201
+ }
202
+
203
+ // Helper methods
204
+ private validateQuoteParams(params: QuoteParams): void {
205
+ if (!this.capabilities.supportedSourceChains.includes(params.fromChain)) {
206
+ throw new ValidationError(`Chain ${params.fromChain} not supported`)
207
+ }
208
+ // ... more validation
209
+ }
210
+
211
+ private mapStatus(backendStatus: string): SwapStatus {
212
+ // Map backend-specific status to SwapStatus enum
213
+ const statusMap = {
214
+ 'waiting': SwapStatus.PENDING_DEPOSIT,
215
+ 'processing': SwapStatus.IN_PROGRESS,
216
+ 'completed': SwapStatus.SUCCESS,
217
+ 'failed': SwapStatus.FAILED,
218
+ }
219
+ return statusMap[backendStatus] ?? SwapStatus.FAILED
220
+ }
221
+ }
222
+ ```
223
+
224
+ ### 2. Optional Methods
225
+
226
+ Implement optional methods for enhanced functionality:
227
+
228
+ ```typescript
229
+ export class MySettlementBackend implements SettlementBackend {
230
+ // ... required methods ...
231
+
232
+ async cancel(swapId: string): Promise<void> {
233
+ if (!this.capabilities.supportsCancellation) {
234
+ throw new ProofError('Cancellation not supported')
235
+ }
236
+
237
+ const status = await this.getStatus(swapId)
238
+ if (status.status !== SwapStatus.PENDING_DEPOSIT) {
239
+ throw new ValidationError('Can only cancel pending swaps')
240
+ }
241
+
242
+ await this.backendCancelSwap(swapId)
243
+ }
244
+
245
+ async waitForCompletion(
246
+ swapId: string,
247
+ options?: { interval?: number; timeout?: number; onStatusChange?: (status: SwapStatusResponse) => void }
248
+ ): Promise<SwapStatusResponse> {
249
+ const interval = options?.interval ?? 5000
250
+ const timeout = options?.timeout ?? 600000
251
+ const startTime = Date.now()
252
+
253
+ while (Date.now() - startTime < timeout) {
254
+ const status = await this.getStatus(swapId)
255
+ options?.onStatusChange?.(status)
256
+
257
+ if (
258
+ status.status === SwapStatus.SUCCESS ||
259
+ status.status === SwapStatus.FAILED ||
260
+ status.status === SwapStatus.REFUNDED
261
+ ) {
262
+ return status
263
+ }
264
+
265
+ await new Promise(resolve => setTimeout(resolve, interval))
266
+ }
267
+
268
+ throw new NetworkError('Swap timeout')
269
+ }
270
+
271
+ async getDryQuote(params: QuoteParams): Promise<Quote> {
272
+ // Return quote without creating deposit address
273
+ return this.getQuote({ ...params, dry: true })
274
+ }
275
+
276
+ async notifyDeposit(
277
+ swapId: string,
278
+ txHash: string,
279
+ metadata?: Record<string, unknown>
280
+ ): Promise<void> {
281
+ await this.backendNotifyDeposit(swapId, txHash, metadata)
282
+ }
283
+ }
284
+ ```
285
+
286
+ ### 3. Factory Function
287
+
288
+ Provide a factory function for easy instantiation:
289
+
290
+ ```typescript
291
+ export function createMyBackend(config: MyBackendConfig): SettlementBackend {
292
+ return new MySettlementBackend(config)
293
+ }
294
+ ```
295
+
296
+ ### 4. Registry Entry
297
+
298
+ Create a registry entry for discoverability:
299
+
300
+ ```typescript
301
+ export const myBackendRegistry: SettlementBackendRegistry = {
302
+ name: 'my-backend',
303
+ factory: createMyBackend,
304
+ displayName: 'My Settlement Backend',
305
+ description: 'Fast and reliable cross-chain swaps',
306
+ homepage: 'https://mybackend.com',
307
+ docs: 'https://docs.mybackend.com',
308
+ }
309
+ ```
310
+
311
+ ## Privacy Support
312
+
313
+ Backends should handle privacy levels appropriately:
314
+
315
+ ### Transparent Mode
316
+
317
+ No privacy features required. Use sender's address directly.
318
+
319
+ ```typescript
320
+ if (params.privacyLevel === PrivacyLevel.TRANSPARENT) {
321
+ // Use senderAddress as both sender and recipient
322
+ recipientAddress = params.senderAddress
323
+ }
324
+ ```
325
+
326
+ ### Shielded Mode
327
+
328
+ Generate stealth address for recipient:
329
+
330
+ ```typescript
331
+ if (params.privacyLevel === PrivacyLevel.SHIELDED) {
332
+ // Generate stealth address from recipientMetaAddress
333
+ const { stealthAddress, ephemeralPublicKey } = generateStealthAddress(
334
+ params.recipientMetaAddress
335
+ )
336
+
337
+ recipientAddress = stealthAddress
338
+ // Store ephemeralPublicKey in metadata for recipient recovery
339
+ }
340
+ ```
341
+
342
+ ### Compliant Mode
343
+
344
+ Same as shielded, but include viewing key hash for auditors:
345
+
346
+ ```typescript
347
+ if (params.privacyLevel === PrivacyLevel.COMPLIANT) {
348
+ // Generate stealth address + viewing key hash
349
+ const { stealthAddress, viewingKeyHash } = generateCompliantAddress(
350
+ params.recipientMetaAddress,
351
+ params.viewingKey
352
+ )
353
+
354
+ recipientAddress = stealthAddress
355
+ // Include viewingKeyHash in metadata for auditors
356
+ }
357
+ ```
358
+
359
+ ## Error Handling
360
+
361
+ Use standard SIP errors:
362
+
363
+ ```typescript
364
+ import { ValidationError, NetworkError, ProofError } from '@sip-protocol/sdk'
365
+
366
+ // Invalid parameters
367
+ throw new ValidationError('Invalid amount', 'amount', { min: 0, received: -1 })
368
+
369
+ // API/network issues
370
+ throw new NetworkError('Backend API unavailable', { status: 503 })
371
+
372
+ // Unsupported features
373
+ throw new ProofError('Feature not supported by this backend')
374
+ ```
375
+
376
+ ## Testing
377
+
378
+ Write comprehensive tests for your backend:
379
+
380
+ ```typescript
381
+ import { describe, it, expect } from 'vitest'
382
+ import { PrivacyLevel } from '@sip-protocol/types'
383
+ import { MySettlementBackend } from './my-backend'
384
+
385
+ describe('MySettlementBackend', () => {
386
+ it('should implement SettlementBackend interface', () => {
387
+ const backend = new MySettlementBackend(config)
388
+
389
+ expect(backend.name).toBe('my-backend')
390
+ expect(backend.capabilities).toBeDefined()
391
+ expect(typeof backend.getQuote).toBe('function')
392
+ expect(typeof backend.executeSwap).toBe('function')
393
+ expect(typeof backend.getStatus).toBe('function')
394
+ })
395
+
396
+ it('should get quote for valid params', async () => {
397
+ const backend = new MySettlementBackend(config)
398
+
399
+ const quote = await backend.getQuote({
400
+ fromChain: 'ethereum',
401
+ toChain: 'near',
402
+ fromToken: 'USDC',
403
+ toToken: 'NEAR',
404
+ amount: 1000000n,
405
+ privacyLevel: PrivacyLevel.TRANSPARENT,
406
+ })
407
+
408
+ expect(quote.quoteId).toBeDefined()
409
+ expect(quote.depositAddress).toBeDefined()
410
+ expect(BigInt(quote.amountOut)).toBeGreaterThan(0n)
411
+ })
412
+
413
+ // ... more tests
414
+ })
415
+ ```
416
+
417
+ ## Examples
418
+
419
+ See existing implementations:
420
+
421
+ - `packages/sdk/src/adapters/near-intents.ts` - NEAR Intents adapter (reference implementation)
422
+ - `packages/sdk/src/zcash/swap-service.ts` - Zcash swap service (privacy-focused)
423
+
424
+ ## Roadmap
425
+
426
+ Planned backends for M11-M12 milestones:
427
+
428
+ - [x] NEAR Intents (M1-M8)
429
+ - [ ] Zcash Settlement Backend (M9)
430
+ - [ ] THORChain Backend (M10)
431
+ - [ ] Direct Chain Backend (M11)
432
+ - [ ] Mina Protocol Backend (M12)
433
+
434
+ ## Resources
435
+
436
+ - [SIP Protocol Documentation](https://docs.sip-protocol.org)
437
+ - [NEAR Intents API](https://1click.chaindefuser.com)
438
+ - [THORChain Docs](https://docs.thorchain.org)
439
+ - [Zcash Shielded Transactions](https://z.cash/technology/zksnarks/)