@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.
- package/dist/browser.d.mts +1 -1
- package/dist/browser.d.ts +1 -1
- package/dist/browser.js +1334 -199
- package/dist/browser.mjs +19 -1
- 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/index-Ba7njCU3.d.ts +6925 -0
- package/dist/index-Co26-vbG.d.mts +6925 -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 +1334 -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/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/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'
|