@sip-protocol/sdk 0.2.10 → 0.3.1
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 +1 -1
- package/dist/browser.d.ts +1 -1
- package/dist/browser.js +1643 -266
- package/dist/browser.mjs +259 -5
- package/dist/chunk-4IFOPYJF.mjs +11950 -0
- package/dist/chunk-4VJHI66K.mjs +12120 -0
- package/dist/chunk-5BAS4D44.mjs +10283 -0
- package/dist/chunk-6WOV2YNG.mjs +10179 -0
- package/dist/chunk-7IMRM7LN.mjs +12149 -0
- package/dist/chunk-DU7LQDD2.mjs +10148 -0
- package/dist/{chunk-AV37IZST.mjs → chunk-JNNXNTSS.mjs} +14 -0
- package/dist/chunk-KXN6IWL5.mjs +10736 -0
- package/dist/chunk-MR7HRCRS.mjs +10165 -0
- package/dist/chunk-NDGUWOOZ.mjs +10157 -0
- package/dist/chunk-O4Y2ZUDL.mjs +12721 -0
- package/dist/chunk-UPTISVCY.mjs +10304 -0
- package/dist/chunk-VITVG25F.mjs +982 -0
- package/dist/chunk-VXSHK7US.mjs +10158 -0
- package/dist/chunk-W3YXIQ7L.mjs +11950 -0
- package/dist/chunk-YZCK337Y.mjs +12155 -0
- package/dist/index-Ba7njCU3.d.ts +6925 -0
- package/dist/index-Co26-vbG.d.mts +6925 -0
- package/dist/index-DAgedMrt.d.ts +6927 -0
- package/dist/index-DW7AQwcU.d.mts +6927 -0
- package/dist/{index-CAhjA4kh.d.mts → index-DqZoHYKI.d.mts} +362 -6
- package/dist/index-dTtK_DTl.d.ts +6762 -0
- package/dist/index-jnkYu-Z4.d.mts +6762 -0
- package/dist/{index-BFOKTz2z.d.ts → index-vB1N1mHd.d.ts} +362 -6
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1340 -199
- package/dist/index.mjs +19 -1
- package/dist/noir-BHQtFvRk.d.mts +467 -0
- package/dist/noir-BHQtFvRk.d.ts +467 -0
- package/package.json +14 -14
- package/src/index.ts +32 -0
- package/src/proofs/worker.ts +240 -4
- package/src/settlement/README.md +439 -0
- package/src/settlement/backends/direct-chain.ts +569 -0
- package/src/settlement/backends/index.ts +22 -0
- package/src/settlement/backends/near-intents.ts +480 -0
- package/src/settlement/backends/zcash-native.ts +516 -0
- package/src/settlement/index.ts +47 -0
- package/src/settlement/interface.ts +397 -0
- package/src/settlement/registry.ts +269 -0
- package/src/settlement/router.ts +383 -0
- package/src/zcash/bridge.ts +20 -2
- package/src/zcash/swap-service.ts +20 -2
- package/LICENSE +0 -21
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Smart Router for Optimal Route Selection
|
|
3
|
+
*
|
|
4
|
+
* Queries all compatible backends and finds the best route based on preferences.
|
|
5
|
+
*
|
|
6
|
+
* @module settlement/router
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { ChainId, PrivacyLevel } from '@sip-protocol/types'
|
|
10
|
+
import type {
|
|
11
|
+
SettlementBackend,
|
|
12
|
+
QuoteParams,
|
|
13
|
+
Quote,
|
|
14
|
+
} from './interface'
|
|
15
|
+
import type { SettlementRegistry } from './registry'
|
|
16
|
+
import { ValidationError, NetworkError } from '../errors'
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Route with quote information
|
|
20
|
+
*/
|
|
21
|
+
export interface RouteWithQuote {
|
|
22
|
+
/** Backend name */
|
|
23
|
+
backend: string
|
|
24
|
+
/** Quote from backend */
|
|
25
|
+
quote: Quote
|
|
26
|
+
/** Backend instance */
|
|
27
|
+
backendInstance: SettlementBackend
|
|
28
|
+
/** Score for ranking (higher is better) */
|
|
29
|
+
score: number
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Quote comparison result
|
|
34
|
+
*/
|
|
35
|
+
export interface QuoteComparison {
|
|
36
|
+
/** All routes with quotes */
|
|
37
|
+
routes: RouteWithQuote[]
|
|
38
|
+
/** Best route by total cost */
|
|
39
|
+
bestByCost: RouteWithQuote | null
|
|
40
|
+
/** Best route by speed */
|
|
41
|
+
bestBySpeed: RouteWithQuote | null
|
|
42
|
+
/** Best route by privacy */
|
|
43
|
+
bestByPrivacy: RouteWithQuote | null
|
|
44
|
+
/** Comparison metadata */
|
|
45
|
+
metadata: {
|
|
46
|
+
/** Total backends queried */
|
|
47
|
+
totalQueried: number
|
|
48
|
+
/** Failed backend queries */
|
|
49
|
+
failures: Array<{ backend: string; error: string }>
|
|
50
|
+
/** Query timestamp */
|
|
51
|
+
queriedAt: number
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Route finding parameters
|
|
57
|
+
*/
|
|
58
|
+
export interface FindBestRouteParams {
|
|
59
|
+
/** Source chain and token */
|
|
60
|
+
from: { chain: ChainId; token: string }
|
|
61
|
+
/** Destination chain and token */
|
|
62
|
+
to: { chain: ChainId; token: string }
|
|
63
|
+
/** Amount to swap (in smallest units) */
|
|
64
|
+
amount: bigint
|
|
65
|
+
/** Privacy level */
|
|
66
|
+
privacyLevel: PrivacyLevel
|
|
67
|
+
/** Prefer speed over cost (default: false) */
|
|
68
|
+
preferSpeed?: boolean
|
|
69
|
+
/** Prefer low fees over speed (default: true) */
|
|
70
|
+
preferLowFees?: boolean
|
|
71
|
+
/** Additional quote parameters */
|
|
72
|
+
recipientMetaAddress?: string
|
|
73
|
+
senderAddress?: string
|
|
74
|
+
slippageTolerance?: number
|
|
75
|
+
deadline?: number
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Smart Router for finding optimal settlement routes
|
|
80
|
+
*
|
|
81
|
+
* Queries all compatible backends in parallel and ranks routes by:
|
|
82
|
+
* - Total cost (network + protocol fees)
|
|
83
|
+
* - Execution speed (estimated time)
|
|
84
|
+
* - Privacy support (shielded vs transparent)
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* const registry = new SettlementRegistry()
|
|
89
|
+
* registry.register(nearIntentsBackend)
|
|
90
|
+
* registry.register(zcashBackend)
|
|
91
|
+
*
|
|
92
|
+
* const router = new SmartRouter(registry)
|
|
93
|
+
* const routes = await router.findBestRoute({
|
|
94
|
+
* from: { chain: 'ethereum', token: 'USDC' },
|
|
95
|
+
* to: { chain: 'solana', token: 'SOL' },
|
|
96
|
+
* amount: 100_000000n,
|
|
97
|
+
* privacyLevel: PrivacyLevel.SHIELDED,
|
|
98
|
+
* preferLowFees: true
|
|
99
|
+
* })
|
|
100
|
+
*
|
|
101
|
+
* // Get best route
|
|
102
|
+
* const best = routes[0]
|
|
103
|
+
* console.log(`Best backend: ${best.backend}`)
|
|
104
|
+
* console.log(`Cost: ${best.quote.fees.totalFeeUSD} USD`)
|
|
105
|
+
* console.log(`Time: ${best.quote.estimatedTime}s`)
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
export class SmartRouter {
|
|
109
|
+
constructor(private registry: SettlementRegistry) {}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Find best routes for a swap
|
|
113
|
+
*
|
|
114
|
+
* Queries all compatible backends in parallel and returns sorted routes.
|
|
115
|
+
*
|
|
116
|
+
* @param params - Route finding parameters
|
|
117
|
+
* @returns Sorted routes (best first)
|
|
118
|
+
* @throws {ValidationError} If no backends support the route
|
|
119
|
+
*/
|
|
120
|
+
async findBestRoute(params: FindBestRouteParams): Promise<RouteWithQuote[]> {
|
|
121
|
+
const {
|
|
122
|
+
from,
|
|
123
|
+
to,
|
|
124
|
+
amount,
|
|
125
|
+
privacyLevel,
|
|
126
|
+
preferSpeed = false,
|
|
127
|
+
preferLowFees = true,
|
|
128
|
+
recipientMetaAddress,
|
|
129
|
+
senderAddress,
|
|
130
|
+
slippageTolerance,
|
|
131
|
+
deadline,
|
|
132
|
+
} = params
|
|
133
|
+
|
|
134
|
+
// Validate amount
|
|
135
|
+
if (amount <= 0n) {
|
|
136
|
+
throw new ValidationError('Amount must be greater than zero')
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Get all registered backends
|
|
140
|
+
const allBackends = this.registry
|
|
141
|
+
.list()
|
|
142
|
+
.map((name) => this.registry.get(name))
|
|
143
|
+
|
|
144
|
+
// Filter backends that support this route and privacy level
|
|
145
|
+
const compatibleBackends = allBackends.filter((backend) => {
|
|
146
|
+
const { supportedSourceChains, supportedDestinationChains, supportedPrivacyLevels } =
|
|
147
|
+
backend.capabilities
|
|
148
|
+
|
|
149
|
+
const supportsRoute =
|
|
150
|
+
supportedSourceChains.includes(from.chain) &&
|
|
151
|
+
supportedDestinationChains.includes(to.chain)
|
|
152
|
+
|
|
153
|
+
const supportsPrivacy = supportedPrivacyLevels.includes(privacyLevel)
|
|
154
|
+
|
|
155
|
+
return supportsRoute && supportsPrivacy
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
if (compatibleBackends.length === 0) {
|
|
159
|
+
throw new ValidationError(
|
|
160
|
+
`No backend supports route from ${from.chain} to ${to.chain} with privacy level ${privacyLevel}`
|
|
161
|
+
)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Build quote params
|
|
165
|
+
const quoteParams: QuoteParams = {
|
|
166
|
+
fromChain: from.chain,
|
|
167
|
+
toChain: to.chain,
|
|
168
|
+
fromToken: from.token,
|
|
169
|
+
toToken: to.token,
|
|
170
|
+
amount,
|
|
171
|
+
privacyLevel,
|
|
172
|
+
recipientMetaAddress,
|
|
173
|
+
senderAddress,
|
|
174
|
+
slippageTolerance,
|
|
175
|
+
deadline,
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Query all compatible backends in parallel
|
|
179
|
+
const quotePromises = compatibleBackends.map(async (backend) => {
|
|
180
|
+
try {
|
|
181
|
+
const quote = await backend.getQuote(quoteParams)
|
|
182
|
+
return {
|
|
183
|
+
backend: backend.name,
|
|
184
|
+
quote,
|
|
185
|
+
backendInstance: backend,
|
|
186
|
+
success: true,
|
|
187
|
+
}
|
|
188
|
+
} catch (error) {
|
|
189
|
+
return {
|
|
190
|
+
backend: backend.name,
|
|
191
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
192
|
+
success: false,
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
const results = await Promise.all(quotePromises)
|
|
198
|
+
|
|
199
|
+
// Filter successful quotes
|
|
200
|
+
const successfulRoutes = results
|
|
201
|
+
.filter((r): r is { backend: string; quote: Quote; backendInstance: SettlementBackend; success: true } => r.success)
|
|
202
|
+
.map((r) => ({
|
|
203
|
+
backend: r.backend,
|
|
204
|
+
quote: r.quote,
|
|
205
|
+
backendInstance: r.backendInstance,
|
|
206
|
+
score: 0, // Will be calculated below
|
|
207
|
+
}))
|
|
208
|
+
|
|
209
|
+
if (successfulRoutes.length === 0) {
|
|
210
|
+
const errors = results
|
|
211
|
+
.filter((r): r is { backend: string; error: string; success: false } => !r.success)
|
|
212
|
+
.map((r) => `${r.backend}: ${r.error}`)
|
|
213
|
+
.join(', ')
|
|
214
|
+
|
|
215
|
+
throw new NetworkError(
|
|
216
|
+
`All backends failed to provide quotes: ${errors}`
|
|
217
|
+
)
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Calculate scores and rank
|
|
221
|
+
this.rankRoutes(successfulRoutes, { preferSpeed, preferLowFees })
|
|
222
|
+
|
|
223
|
+
// Sort by score (highest first)
|
|
224
|
+
successfulRoutes.sort((a, b) => b.score - a.score)
|
|
225
|
+
|
|
226
|
+
return successfulRoutes
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Compare quotes from multiple routes side-by-side
|
|
231
|
+
*
|
|
232
|
+
* @param routes - Routes to compare (from findBestRoute)
|
|
233
|
+
* @returns Comparison with best routes by different criteria
|
|
234
|
+
*/
|
|
235
|
+
compareQuotes(routes: RouteWithQuote[]): QuoteComparison {
|
|
236
|
+
if (routes.length === 0) {
|
|
237
|
+
return {
|
|
238
|
+
routes: [],
|
|
239
|
+
bestByCost: null,
|
|
240
|
+
bestBySpeed: null,
|
|
241
|
+
bestByPrivacy: null,
|
|
242
|
+
metadata: {
|
|
243
|
+
totalQueried: 0,
|
|
244
|
+
failures: [],
|
|
245
|
+
queriedAt: Date.now(),
|
|
246
|
+
},
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Find best by cost (lowest total fee)
|
|
251
|
+
const bestByCost = [...routes].sort((a, b) => {
|
|
252
|
+
const costA = this.calculateTotalCost(a.quote)
|
|
253
|
+
const costB = this.calculateTotalCost(b.quote)
|
|
254
|
+
return costA - costB
|
|
255
|
+
})[0]
|
|
256
|
+
|
|
257
|
+
// Find best by speed (lowest estimated time)
|
|
258
|
+
const bestBySpeed = [...routes].sort((a, b) => {
|
|
259
|
+
const timeA = a.quote.estimatedTime ?? Infinity
|
|
260
|
+
const timeB = b.quote.estimatedTime ?? Infinity
|
|
261
|
+
return timeA - timeB
|
|
262
|
+
})[0]
|
|
263
|
+
|
|
264
|
+
// Find best by privacy (full shielded support)
|
|
265
|
+
const bestByPrivacy = [...routes].find((route) => {
|
|
266
|
+
const { supportedPrivacyLevels } = route.backendInstance.capabilities
|
|
267
|
+
return (
|
|
268
|
+
supportedPrivacyLevels.includes('shielded' as PrivacyLevel) ||
|
|
269
|
+
supportedPrivacyLevels.includes('compliant' as PrivacyLevel)
|
|
270
|
+
)
|
|
271
|
+
}) || routes[0]
|
|
272
|
+
|
|
273
|
+
return {
|
|
274
|
+
routes,
|
|
275
|
+
bestByCost,
|
|
276
|
+
bestBySpeed,
|
|
277
|
+
bestByPrivacy,
|
|
278
|
+
metadata: {
|
|
279
|
+
totalQueried: routes.length,
|
|
280
|
+
failures: [], // Could track from findBestRoute
|
|
281
|
+
queriedAt: Date.now(),
|
|
282
|
+
},
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Rank routes by score
|
|
288
|
+
*
|
|
289
|
+
* Scoring algorithm:
|
|
290
|
+
* - Base score: 100
|
|
291
|
+
* - Cost: Lower fees = higher score (up to +50)
|
|
292
|
+
* - Speed: Faster execution = higher score (up to +30)
|
|
293
|
+
* - Privacy: Better privacy support = higher score (up to +20)
|
|
294
|
+
*
|
|
295
|
+
* @private
|
|
296
|
+
*/
|
|
297
|
+
private rankRoutes(
|
|
298
|
+
routes: RouteWithQuote[],
|
|
299
|
+
preferences: { preferSpeed: boolean; preferLowFees: boolean }
|
|
300
|
+
): void {
|
|
301
|
+
const { preferSpeed, preferLowFees } = preferences
|
|
302
|
+
|
|
303
|
+
// Calculate min/max for normalization
|
|
304
|
+
const costs = routes.map((r) => this.calculateTotalCost(r.quote))
|
|
305
|
+
const times = routes.map((r) => r.quote.estimatedTime ?? Infinity)
|
|
306
|
+
|
|
307
|
+
const minCost = Math.min(...costs)
|
|
308
|
+
const maxCost = Math.max(...costs)
|
|
309
|
+
const minTime = Math.min(...times.filter(t => t !== Infinity))
|
|
310
|
+
const maxTime = Math.max(...times.filter(t => t !== Infinity))
|
|
311
|
+
|
|
312
|
+
// Assign scores
|
|
313
|
+
routes.forEach((route, index) => {
|
|
314
|
+
let score = 100 // Base score
|
|
315
|
+
|
|
316
|
+
// Cost scoring (0-50 points)
|
|
317
|
+
if (maxCost > minCost) {
|
|
318
|
+
const costNormalized = 1 - (costs[index] - minCost) / (maxCost - minCost)
|
|
319
|
+
const costWeight = preferLowFees ? 50 : 30
|
|
320
|
+
score += costNormalized * costWeight
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Speed scoring (0-30 points)
|
|
324
|
+
const time = times[index]
|
|
325
|
+
if (time !== Infinity && maxTime > minTime) {
|
|
326
|
+
const speedNormalized = 1 - (time - minTime) / (maxTime - minTime)
|
|
327
|
+
const speedWeight = preferSpeed ? 50 : 30
|
|
328
|
+
score += speedNormalized * speedWeight
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Privacy scoring (0-20 points)
|
|
332
|
+
const { supportedPrivacyLevels } = route.backendInstance.capabilities
|
|
333
|
+
if (supportedPrivacyLevels.includes('shielded' as PrivacyLevel)) {
|
|
334
|
+
score += 20
|
|
335
|
+
} else if (supportedPrivacyLevels.includes('compliant' as PrivacyLevel)) {
|
|
336
|
+
score += 10
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
route.score = score
|
|
340
|
+
})
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Calculate total cost from quote
|
|
345
|
+
*
|
|
346
|
+
* Returns total fee in USD if available, otherwise estimates from fees
|
|
347
|
+
*
|
|
348
|
+
* @private
|
|
349
|
+
*/
|
|
350
|
+
private calculateTotalCost(quote: Quote): number {
|
|
351
|
+
// Use totalFeeUSD if available
|
|
352
|
+
if (quote.fees.totalFeeUSD) {
|
|
353
|
+
return parseFloat(quote.fees.totalFeeUSD)
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Otherwise estimate from network + protocol fees
|
|
357
|
+
// This is a rough estimate - real implementation would need price feeds
|
|
358
|
+
const networkFee = parseFloat(quote.fees.networkFee) || 0
|
|
359
|
+
const protocolFee = parseFloat(quote.fees.protocolFee) || 0
|
|
360
|
+
|
|
361
|
+
return networkFee + protocolFee
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Create a new SmartRouter instance
|
|
367
|
+
*
|
|
368
|
+
* @param registry - Settlement registry with registered backends
|
|
369
|
+
* @returns SmartRouter instance
|
|
370
|
+
*
|
|
371
|
+
* @example
|
|
372
|
+
* ```typescript
|
|
373
|
+
* const registry = new SettlementRegistry()
|
|
374
|
+
* registry.register(nearIntentsBackend)
|
|
375
|
+
* registry.register(zcashBackend)
|
|
376
|
+
*
|
|
377
|
+
* const router = createSmartRouter(registry)
|
|
378
|
+
* const routes = await router.findBestRoute({ ... })
|
|
379
|
+
* ```
|
|
380
|
+
*/
|
|
381
|
+
export function createSmartRouter(registry: SettlementRegistry): SmartRouter {
|
|
382
|
+
return new SmartRouter(registry)
|
|
383
|
+
}
|
package/src/zcash/bridge.ts
CHANGED
|
@@ -126,7 +126,7 @@ export interface ZcashBridgeConfig {
|
|
|
126
126
|
zcashService?: ZcashShieldedService
|
|
127
127
|
/** Operating mode */
|
|
128
128
|
mode: 'demo' | 'production'
|
|
129
|
-
/** External bridge provider for production */
|
|
129
|
+
/** External bridge provider (required for production mode) */
|
|
130
130
|
bridgeProvider?: BridgeProvider
|
|
131
131
|
/** Price feed for conversions */
|
|
132
132
|
priceFeed?: PriceFeed
|
|
@@ -150,7 +150,15 @@ const TOKEN_DECIMALS: Record<string, number> = {
|
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
/**
|
|
153
|
-
* Mock prices for demo mode
|
|
153
|
+
* Mock prices for demo mode calculations.
|
|
154
|
+
*
|
|
155
|
+
* ⚠️ DEMO VALUES ONLY - Not for production use!
|
|
156
|
+
*
|
|
157
|
+
* These prices are approximate values for testing and demonstration.
|
|
158
|
+
* They do not reflect real market conditions.
|
|
159
|
+
*
|
|
160
|
+
* @lastUpdated 2024-12-03
|
|
161
|
+
* @note Update quarterly or when prices diverge significantly from market
|
|
154
162
|
*/
|
|
155
163
|
const MOCK_PRICES: Record<string, number> = {
|
|
156
164
|
ETH: 2500,
|
|
@@ -189,6 +197,8 @@ const ROUTE_CONFIG: Record<string, { minUsd: number; maxUsd: number; feeBps: num
|
|
|
189
197
|
*
|
|
190
198
|
* Bridges tokens from Ethereum, Solana, and other chains to Zcash,
|
|
191
199
|
* with optional shielding to z-addresses.
|
|
200
|
+
*
|
|
201
|
+
* @throws {IntentError} If production mode is configured without a bridge provider
|
|
192
202
|
*/
|
|
193
203
|
export class ZcashBridge {
|
|
194
204
|
private readonly config: Required<Omit<ZcashBridgeConfig, 'zcashService' | 'bridgeProvider' | 'priceFeed'>>
|
|
@@ -198,6 +208,14 @@ export class ZcashBridge {
|
|
|
198
208
|
private readonly bridgeRequests: Map<string, BridgeResult> = new Map()
|
|
199
209
|
|
|
200
210
|
constructor(config: ZcashBridgeConfig) {
|
|
211
|
+
// Fail-fast validation for production mode
|
|
212
|
+
if (config.mode === 'production' && !config.bridgeProvider) {
|
|
213
|
+
throw new IntentError(
|
|
214
|
+
'Bridge provider required for production mode',
|
|
215
|
+
ErrorCode.INTENT_INVALID_STATE,
|
|
216
|
+
)
|
|
217
|
+
}
|
|
218
|
+
|
|
201
219
|
this.config = {
|
|
202
220
|
mode: config.mode,
|
|
203
221
|
defaultSlippage: config.defaultSlippage ?? 100,
|
|
@@ -55,7 +55,7 @@ export interface ZcashSwapServiceConfig {
|
|
|
55
55
|
zcashService?: ZcashShieldedService
|
|
56
56
|
/** Operating mode */
|
|
57
57
|
mode: 'demo' | 'production'
|
|
58
|
-
/** Bridge provider (for production) */
|
|
58
|
+
/** Bridge provider (required for production mode) */
|
|
59
59
|
bridgeProvider?: BridgeProvider
|
|
60
60
|
/** Price feed for quotes */
|
|
61
61
|
priceFeed?: PriceFeed
|
|
@@ -245,7 +245,15 @@ export type ZcashSwapStatus =
|
|
|
245
245
|
// ─── Mock Price Data ───────────────────────────────────────────────────────────
|
|
246
246
|
|
|
247
247
|
/**
|
|
248
|
-
* Mock prices for demo mode
|
|
248
|
+
* Mock prices for demo mode calculations.
|
|
249
|
+
*
|
|
250
|
+
* ⚠️ DEMO VALUES ONLY - Not for production use!
|
|
251
|
+
*
|
|
252
|
+
* These prices are approximate values for testing and demonstration.
|
|
253
|
+
* They do not reflect real market conditions.
|
|
254
|
+
*
|
|
255
|
+
* @lastUpdated 2024-12-03
|
|
256
|
+
* @note Update quarterly or when prices diverge significantly from market
|
|
249
257
|
*/
|
|
250
258
|
const MOCK_PRICES: Record<string, number> = {
|
|
251
259
|
ETH: 2500,
|
|
@@ -276,6 +284,8 @@ const TOKEN_DECIMALS: Record<string, number> = {
|
|
|
276
284
|
* Zcash Swap Service
|
|
277
285
|
*
|
|
278
286
|
* Enables cross-chain swaps from ETH/SOL/NEAR to Zcash's shielded pool.
|
|
287
|
+
*
|
|
288
|
+
* @throws {IntentError} If production mode is configured without a bridge provider
|
|
279
289
|
*/
|
|
280
290
|
export class ZcashSwapService {
|
|
281
291
|
private readonly config: Required<Omit<ZcashSwapServiceConfig, 'zcashService' | 'bridgeProvider' | 'priceFeed'>>
|
|
@@ -286,6 +296,14 @@ export class ZcashSwapService {
|
|
|
286
296
|
private readonly swaps: Map<string, ZcashSwapResult> = new Map()
|
|
287
297
|
|
|
288
298
|
constructor(config: ZcashSwapServiceConfig) {
|
|
299
|
+
// Fail-fast validation for production mode
|
|
300
|
+
if (config.mode === 'production' && !config.bridgeProvider) {
|
|
301
|
+
throw new IntentError(
|
|
302
|
+
'Bridge provider required for production mode',
|
|
303
|
+
ErrorCode.INTENT_INVALID_STATE,
|
|
304
|
+
)
|
|
305
|
+
}
|
|
306
|
+
|
|
289
307
|
this.config = {
|
|
290
308
|
mode: config.mode,
|
|
291
309
|
defaultSlippage: config.defaultSlippage ?? 100, // 1%
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025 RECTOR Labs
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|