@sip-protocol/react 0.1.0 → 0.1.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/README.md +54 -14
- package/dist/index.d.mts +1224 -6
- package/dist/index.d.ts +1224 -6
- package/dist/index.js +5783 -10
- package/dist/index.mjs +5777 -9
- package/package.json +9 -8
- package/src/components/ethereum/index.ts +55 -0
- package/src/components/ethereum/privacy-toggle.tsx +822 -0
- package/src/components/ethereum/stealth-address-display.tsx +1050 -0
- package/src/components/ethereum/transaction-history.tsx +1187 -0
- package/src/components/ethereum/transaction-tracker.tsx +302 -0
- package/src/components/ethereum/viewing-key-manager.tsx +228 -0
- package/src/components/index.ts +107 -0
- package/src/components/privacy-toggle.tsx +548 -0
- package/src/components/stealth-address-display.tsx +770 -0
- package/src/components/transaction-history.tsx +651 -0
- package/src/components/transaction-tracker.tsx +1079 -0
- package/src/components/viewing-key-manager.tsx +1576 -0
- package/src/hooks/index.ts +61 -0
- package/src/hooks/use-privacy-advisor.ts +371 -0
- package/src/hooks/use-private-swap.ts +5 -5
- package/src/hooks/use-proof-composition.ts +654 -0
- package/src/hooks/use-scan-payments.ts +504 -0
- package/src/hooks/use-stealth-address.ts +23 -7
- package/src/hooks/use-stealth-transfer.ts +284 -0
- package/src/hooks/use-transaction-history.ts +435 -0
- package/src/index.ts +75 -0
package/src/hooks/index.ts
CHANGED
|
@@ -8,3 +8,64 @@ export {
|
|
|
8
8
|
type SwapResult,
|
|
9
9
|
} from './use-private-swap'
|
|
10
10
|
export { useViewingKey } from './use-viewing-key'
|
|
11
|
+
|
|
12
|
+
// Solana same-chain privacy hooks
|
|
13
|
+
export {
|
|
14
|
+
useStealthTransfer,
|
|
15
|
+
type TransferStatus,
|
|
16
|
+
type UseStealthTransferParams,
|
|
17
|
+
type TransferParams,
|
|
18
|
+
type UseStealthTransferReturn,
|
|
19
|
+
} from './use-stealth-transfer'
|
|
20
|
+
|
|
21
|
+
export {
|
|
22
|
+
useScanPayments,
|
|
23
|
+
type ScanStatus,
|
|
24
|
+
type UseScanPaymentsParams,
|
|
25
|
+
type PaymentWithStatus,
|
|
26
|
+
type UseScanPaymentsReturn,
|
|
27
|
+
type ClaimParams,
|
|
28
|
+
type ClaimAllParams,
|
|
29
|
+
type ClaimAllResult,
|
|
30
|
+
type MintResolver,
|
|
31
|
+
} from './use-scan-payments'
|
|
32
|
+
|
|
33
|
+
// Privacy Advisor hook (LangChain-powered)
|
|
34
|
+
export {
|
|
35
|
+
usePrivacyAdvisor,
|
|
36
|
+
type UsePrivacyAdvisorParams,
|
|
37
|
+
type UsePrivacyAdvisorReturn,
|
|
38
|
+
} from './use-privacy-advisor'
|
|
39
|
+
|
|
40
|
+
// NEAR Transaction History (M17-NEAR-20)
|
|
41
|
+
export {
|
|
42
|
+
useTransactionHistory,
|
|
43
|
+
type HistoryStatus,
|
|
44
|
+
type UseTransactionHistoryParams,
|
|
45
|
+
type HistoryFilters,
|
|
46
|
+
type TransactionSummary,
|
|
47
|
+
type UseTransactionHistoryReturn,
|
|
48
|
+
} from './use-transaction-history'
|
|
49
|
+
|
|
50
|
+
// Proof Composition Hooks (M20-17)
|
|
51
|
+
export {
|
|
52
|
+
// Main hooks
|
|
53
|
+
useProofComposer,
|
|
54
|
+
useProofVerification,
|
|
55
|
+
useComposedProof,
|
|
56
|
+
useProofCache,
|
|
57
|
+
useSystemCompatibility,
|
|
58
|
+
// Types
|
|
59
|
+
type ProofOperationStatus,
|
|
60
|
+
type UseProofComposerConfig,
|
|
61
|
+
type UseProofComposerReturn,
|
|
62
|
+
type UseProofVerificationConfig,
|
|
63
|
+
type UseProofVerificationReturn,
|
|
64
|
+
type UseComposedProofConfig,
|
|
65
|
+
type UseComposedProofReturn,
|
|
66
|
+
type UseProofCacheConfig,
|
|
67
|
+
type UseProofCacheReturn,
|
|
68
|
+
type UseSystemCompatibilityReturn,
|
|
69
|
+
} from './use-proof-composition'
|
|
70
|
+
|
|
71
|
+
// Note: useProofGeneration and useProofQueue will be added after M20-14 merges
|
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
import { useState, useCallback, useRef, useMemo } from 'react'
|
|
2
|
+
import {
|
|
3
|
+
PrivacyAdvisorAgent,
|
|
4
|
+
createPrivacyAdvisor,
|
|
5
|
+
createSurveillanceAnalyzer,
|
|
6
|
+
} from '@sip-protocol/sdk'
|
|
7
|
+
import type {
|
|
8
|
+
PrivacyAdvisorConfig,
|
|
9
|
+
AdvisoryContext,
|
|
10
|
+
AdvisorResponse,
|
|
11
|
+
PrivacyAdvisoryReport,
|
|
12
|
+
AdvisorMessage,
|
|
13
|
+
AdvisorStatus,
|
|
14
|
+
FullAnalysisResult,
|
|
15
|
+
} from '@sip-protocol/sdk'
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Parameters for usePrivacyAdvisor hook
|
|
19
|
+
*/
|
|
20
|
+
export interface UsePrivacyAdvisorParams {
|
|
21
|
+
/** OpenAI API key for the advisor */
|
|
22
|
+
openaiApiKey: string
|
|
23
|
+
/** Helius API key for wallet analysis */
|
|
24
|
+
heliusApiKey: string
|
|
25
|
+
/** Model to use (default: gpt-4o-mini for cost efficiency) */
|
|
26
|
+
model?: PrivacyAdvisorConfig['model']
|
|
27
|
+
/** Temperature for responses (0-1, default: 0.3) */
|
|
28
|
+
temperature?: number
|
|
29
|
+
/** Enable streaming responses */
|
|
30
|
+
enableStreaming?: boolean
|
|
31
|
+
/** Solana cluster */
|
|
32
|
+
cluster?: 'mainnet-beta' | 'devnet'
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Return type for usePrivacyAdvisor hook
|
|
37
|
+
*/
|
|
38
|
+
export interface UsePrivacyAdvisorReturn {
|
|
39
|
+
/** Current advisor status */
|
|
40
|
+
status: AdvisorStatus
|
|
41
|
+
/** Whether the advisor is processing */
|
|
42
|
+
isLoading: boolean
|
|
43
|
+
/** Error message if operation failed */
|
|
44
|
+
error: Error | null
|
|
45
|
+
/** Conversation messages */
|
|
46
|
+
messages: AdvisorMessage[]
|
|
47
|
+
/** Current privacy report (if generated) */
|
|
48
|
+
report: PrivacyAdvisoryReport | null
|
|
49
|
+
/** Current analysis result (if analyzed) */
|
|
50
|
+
analysisResult: FullAnalysisResult | null
|
|
51
|
+
/** Suggested follow-up questions */
|
|
52
|
+
suggestedQuestions: string[]
|
|
53
|
+
/** Total cost of API calls in this session */
|
|
54
|
+
totalCost: number
|
|
55
|
+
/** Analyze a wallet and get recommendations */
|
|
56
|
+
analyzeWallet: (walletAddress: string, query?: string) => Promise<AdvisorResponse | null>
|
|
57
|
+
/** Send a chat message (follow-up question) */
|
|
58
|
+
chat: (message: string) => Promise<AdvisorResponse | null>
|
|
59
|
+
/** Clear conversation history and reset */
|
|
60
|
+
reset: () => void
|
|
61
|
+
/** Clear error */
|
|
62
|
+
clearError: () => void
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* usePrivacyAdvisor - AI-powered privacy recommendations for Solana wallets
|
|
67
|
+
*
|
|
68
|
+
* @remarks
|
|
69
|
+
* This hook provides a React-friendly interface for the Privacy Advisor Agent.
|
|
70
|
+
* It combines wallet surveillance analysis with LangChain-powered AI recommendations.
|
|
71
|
+
*
|
|
72
|
+
* Features:
|
|
73
|
+
* - Analyze any Solana wallet's privacy exposure
|
|
74
|
+
* - Get AI-generated recommendations in plain English
|
|
75
|
+
* - Chat for follow-up questions
|
|
76
|
+
* - Track API costs
|
|
77
|
+
* - Streaming support for real-time responses
|
|
78
|
+
*
|
|
79
|
+
* @param params - Hook configuration parameters
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```tsx
|
|
83
|
+
* import { usePrivacyAdvisor } from '@sip-protocol/react'
|
|
84
|
+
*
|
|
85
|
+
* function PrivacyDashboard() {
|
|
86
|
+
* const {
|
|
87
|
+
* status,
|
|
88
|
+
* messages,
|
|
89
|
+
* report,
|
|
90
|
+
* suggestedQuestions,
|
|
91
|
+
* analyzeWallet,
|
|
92
|
+
* chat,
|
|
93
|
+
* } = usePrivacyAdvisor({
|
|
94
|
+
* openaiApiKey: process.env.NEXT_PUBLIC_OPENAI_API_KEY!,
|
|
95
|
+
* heliusApiKey: process.env.NEXT_PUBLIC_HELIUS_API_KEY!,
|
|
96
|
+
* })
|
|
97
|
+
*
|
|
98
|
+
* const handleAnalyze = async () => {
|
|
99
|
+
* await analyzeWallet('7xK9abc123...', 'What should I fix first?')
|
|
100
|
+
* }
|
|
101
|
+
*
|
|
102
|
+
* return (
|
|
103
|
+
* <div>
|
|
104
|
+
* <button onClick={handleAnalyze} disabled={status !== 'idle'}>
|
|
105
|
+
* Analyze My Wallet
|
|
106
|
+
* </button>
|
|
107
|
+
*
|
|
108
|
+
* {report && (
|
|
109
|
+
* <div>
|
|
110
|
+
* <h2>Privacy Score: {report.currentScore}/100</h2>
|
|
111
|
+
* <p>{report.summary}</p>
|
|
112
|
+
*
|
|
113
|
+
* <h3>Recommendations</h3>
|
|
114
|
+
* {report.recommendations.map((rec) => (
|
|
115
|
+
* <div key={rec.id}>
|
|
116
|
+
* <h4>{rec.title}</h4>
|
|
117
|
+
* <p>{rec.explanation}</p>
|
|
118
|
+
* <ul>
|
|
119
|
+
* {rec.actions.map((action, i) => (
|
|
120
|
+
* <li key={i}>{action}</li>
|
|
121
|
+
* ))}
|
|
122
|
+
* </ul>
|
|
123
|
+
* </div>
|
|
124
|
+
* ))}
|
|
125
|
+
* </div>
|
|
126
|
+
* )}
|
|
127
|
+
*
|
|
128
|
+
* <h3>Follow-up Questions</h3>
|
|
129
|
+
* {suggestedQuestions.map((q, i) => (
|
|
130
|
+
* <button key={i} onClick={() => chat(q)}>
|
|
131
|
+
* {q}
|
|
132
|
+
* </button>
|
|
133
|
+
* ))}
|
|
134
|
+
*
|
|
135
|
+
* <h3>Conversation</h3>
|
|
136
|
+
* {messages.map((msg, i) => (
|
|
137
|
+
* <div key={i} className={msg.role}>
|
|
138
|
+
* {msg.content}
|
|
139
|
+
* </div>
|
|
140
|
+
* ))}
|
|
141
|
+
* </div>
|
|
142
|
+
* )
|
|
143
|
+
* }
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
export function usePrivacyAdvisor(
|
|
147
|
+
params: UsePrivacyAdvisorParams
|
|
148
|
+
): UsePrivacyAdvisorReturn {
|
|
149
|
+
const {
|
|
150
|
+
openaiApiKey,
|
|
151
|
+
heliusApiKey,
|
|
152
|
+
model = 'gpt-4o-mini',
|
|
153
|
+
temperature = 0.3,
|
|
154
|
+
enableStreaming = false,
|
|
155
|
+
cluster = 'mainnet-beta',
|
|
156
|
+
} = params
|
|
157
|
+
|
|
158
|
+
const [status, setStatus] = useState<AdvisorStatus>('idle')
|
|
159
|
+
const [error, setError] = useState<Error | null>(null)
|
|
160
|
+
const [messages, setMessages] = useState<AdvisorMessage[]>([])
|
|
161
|
+
const [report, setReport] = useState<PrivacyAdvisoryReport | null>(null)
|
|
162
|
+
const [analysisResult, setAnalysisResult] = useState<FullAnalysisResult | null>(null)
|
|
163
|
+
const [suggestedQuestions, setSuggestedQuestions] = useState<string[]>([])
|
|
164
|
+
const [totalCost, setTotalCost] = useState(0)
|
|
165
|
+
|
|
166
|
+
// Memoize agent instances
|
|
167
|
+
const advisor = useMemo(
|
|
168
|
+
() =>
|
|
169
|
+
createPrivacyAdvisor({
|
|
170
|
+
openaiApiKey,
|
|
171
|
+
model,
|
|
172
|
+
temperature,
|
|
173
|
+
}),
|
|
174
|
+
[openaiApiKey, model, temperature]
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
const analyzer = useMemo(
|
|
178
|
+
() =>
|
|
179
|
+
createSurveillanceAnalyzer({
|
|
180
|
+
heliusApiKey,
|
|
181
|
+
cluster,
|
|
182
|
+
}),
|
|
183
|
+
[heliusApiKey, cluster]
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
// Keep reference to latest analysis for chat context
|
|
187
|
+
const analysisRef = useRef<FullAnalysisResult | null>(null)
|
|
188
|
+
|
|
189
|
+
const isLoading = status === 'analyzing' || status === 'thinking' || status === 'responding'
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Analyze a wallet and get recommendations
|
|
193
|
+
*/
|
|
194
|
+
const analyzeWallet = useCallback(
|
|
195
|
+
async (
|
|
196
|
+
walletAddress: string,
|
|
197
|
+
query?: string
|
|
198
|
+
): Promise<AdvisorResponse | null> => {
|
|
199
|
+
setStatus('analyzing')
|
|
200
|
+
setError(null)
|
|
201
|
+
|
|
202
|
+
try {
|
|
203
|
+
// First, run surveillance analysis
|
|
204
|
+
const analysis = await analyzer.analyze(walletAddress)
|
|
205
|
+
setAnalysisResult(analysis)
|
|
206
|
+
analysisRef.current = analysis
|
|
207
|
+
|
|
208
|
+
setStatus('thinking')
|
|
209
|
+
|
|
210
|
+
// Build context for advisor
|
|
211
|
+
const context: AdvisoryContext = {
|
|
212
|
+
analysisResult: analysis,
|
|
213
|
+
userQuery: query,
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
let response: AdvisorResponse
|
|
217
|
+
|
|
218
|
+
if (enableStreaming) {
|
|
219
|
+
// Stream response
|
|
220
|
+
setStatus('responding')
|
|
221
|
+
let streamedContent = ''
|
|
222
|
+
|
|
223
|
+
response = await advisor.stream(context, (chunk) => {
|
|
224
|
+
streamedContent += chunk
|
|
225
|
+
// Update messages with partial content
|
|
226
|
+
setMessages((prev) => {
|
|
227
|
+
const filtered = prev.filter((m) => m.role !== 'assistant' || m.content !== streamedContent.slice(0, -chunk.length))
|
|
228
|
+
return [
|
|
229
|
+
...filtered,
|
|
230
|
+
{
|
|
231
|
+
role: 'assistant' as const,
|
|
232
|
+
content: streamedContent,
|
|
233
|
+
timestamp: Date.now(),
|
|
234
|
+
},
|
|
235
|
+
]
|
|
236
|
+
})
|
|
237
|
+
})
|
|
238
|
+
} else {
|
|
239
|
+
// Regular response
|
|
240
|
+
setStatus('responding')
|
|
241
|
+
response = await advisor.analyze(context)
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Update state
|
|
245
|
+
if (response.report) {
|
|
246
|
+
setReport(response.report)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (response.suggestedQuestions) {
|
|
250
|
+
setSuggestedQuestions(response.suggestedQuestions)
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (response.usage) {
|
|
254
|
+
setTotalCost((prev) => prev + response.usage!.estimatedCost)
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Add messages
|
|
258
|
+
setMessages((prev) => [
|
|
259
|
+
...prev,
|
|
260
|
+
{
|
|
261
|
+
role: 'user' as const,
|
|
262
|
+
content: query || `Analyze wallet ${walletAddress}`,
|
|
263
|
+
timestamp: Date.now(),
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
role: 'assistant' as const,
|
|
267
|
+
content: response.message,
|
|
268
|
+
timestamp: Date.now(),
|
|
269
|
+
},
|
|
270
|
+
])
|
|
271
|
+
|
|
272
|
+
setStatus('idle')
|
|
273
|
+
return response
|
|
274
|
+
} catch (err) {
|
|
275
|
+
const error = err instanceof Error ? err : new Error('Analysis failed')
|
|
276
|
+
setError(error)
|
|
277
|
+
setStatus('error')
|
|
278
|
+
return null
|
|
279
|
+
}
|
|
280
|
+
},
|
|
281
|
+
[advisor, analyzer, enableStreaming]
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Send a chat message (follow-up question)
|
|
286
|
+
*/
|
|
287
|
+
const chat = useCallback(
|
|
288
|
+
async (message: string): Promise<AdvisorResponse | null> => {
|
|
289
|
+
setStatus('thinking')
|
|
290
|
+
setError(null)
|
|
291
|
+
|
|
292
|
+
try {
|
|
293
|
+
// Build context with latest analysis if available
|
|
294
|
+
const context: AdvisoryContext | undefined = analysisRef.current
|
|
295
|
+
? { analysisResult: analysisRef.current }
|
|
296
|
+
: undefined
|
|
297
|
+
|
|
298
|
+
setStatus('responding')
|
|
299
|
+
const response = await advisor.chat(message, context)
|
|
300
|
+
|
|
301
|
+
if (response.usage) {
|
|
302
|
+
setTotalCost((prev) => prev + response.usage!.estimatedCost)
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Add messages
|
|
306
|
+
setMessages((prev) => [
|
|
307
|
+
...prev,
|
|
308
|
+
{
|
|
309
|
+
role: 'user' as const,
|
|
310
|
+
content: message,
|
|
311
|
+
timestamp: Date.now(),
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
role: 'assistant' as const,
|
|
315
|
+
content: response.message,
|
|
316
|
+
timestamp: Date.now(),
|
|
317
|
+
},
|
|
318
|
+
])
|
|
319
|
+
|
|
320
|
+
setStatus('idle')
|
|
321
|
+
return response
|
|
322
|
+
} catch (err) {
|
|
323
|
+
const error = err instanceof Error ? err : new Error('Chat failed')
|
|
324
|
+
setError(error)
|
|
325
|
+
setStatus('error')
|
|
326
|
+
return null
|
|
327
|
+
}
|
|
328
|
+
},
|
|
329
|
+
[advisor]
|
|
330
|
+
)
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Reset all state
|
|
334
|
+
*/
|
|
335
|
+
const reset = useCallback(() => {
|
|
336
|
+
setStatus('idle')
|
|
337
|
+
setError(null)
|
|
338
|
+
setMessages([])
|
|
339
|
+
setReport(null)
|
|
340
|
+
setAnalysisResult(null)
|
|
341
|
+
setSuggestedQuestions([])
|
|
342
|
+
setTotalCost(0)
|
|
343
|
+
analysisRef.current = null
|
|
344
|
+
advisor.clearHistory()
|
|
345
|
+
}, [advisor])
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Clear error state
|
|
349
|
+
*/
|
|
350
|
+
const clearError = useCallback(() => {
|
|
351
|
+
setError(null)
|
|
352
|
+
if (status === 'error') {
|
|
353
|
+
setStatus('idle')
|
|
354
|
+
}
|
|
355
|
+
}, [status])
|
|
356
|
+
|
|
357
|
+
return {
|
|
358
|
+
status,
|
|
359
|
+
isLoading,
|
|
360
|
+
error,
|
|
361
|
+
messages,
|
|
362
|
+
report,
|
|
363
|
+
analysisResult,
|
|
364
|
+
suggestedQuestions,
|
|
365
|
+
totalCost,
|
|
366
|
+
analyzeWallet,
|
|
367
|
+
chat,
|
|
368
|
+
reset,
|
|
369
|
+
clearError,
|
|
370
|
+
}
|
|
371
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useState, useCallback } from 'react'
|
|
2
2
|
import { useSIP } from './use-sip'
|
|
3
|
-
import type { Quote, PrivacyLevel, CreateIntentParams, TrackedIntent, FulfillmentResult } from '@sip-protocol/types'
|
|
3
|
+
import type { Quote, PrivacyLevel, CreateIntentParams, TrackedIntent, FulfillmentResult, ChainId } from '@sip-protocol/types'
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Status of the swap lifecycle
|
|
@@ -136,7 +136,7 @@ export function usePrivateSwap() {
|
|
|
136
136
|
const intentParams: CreateIntentParams = {
|
|
137
137
|
input: {
|
|
138
138
|
asset: {
|
|
139
|
-
chain: params.inputChain as
|
|
139
|
+
chain: params.inputChain as ChainId,
|
|
140
140
|
symbol: params.inputToken,
|
|
141
141
|
address: null,
|
|
142
142
|
decimals: 9, // Default, should be configurable
|
|
@@ -145,7 +145,7 @@ export function usePrivateSwap() {
|
|
|
145
145
|
},
|
|
146
146
|
output: {
|
|
147
147
|
asset: {
|
|
148
|
-
chain: params.outputChain as
|
|
148
|
+
chain: params.outputChain as ChainId,
|
|
149
149
|
symbol: params.outputToken,
|
|
150
150
|
address: null,
|
|
151
151
|
decimals: 18, // Default, should be configurable
|
|
@@ -192,7 +192,7 @@ export function usePrivateSwap() {
|
|
|
192
192
|
const intentParams: CreateIntentParams = {
|
|
193
193
|
input: {
|
|
194
194
|
asset: {
|
|
195
|
-
chain: params.input.chain as
|
|
195
|
+
chain: params.input.chain as ChainId,
|
|
196
196
|
symbol: params.input.token,
|
|
197
197
|
address: null,
|
|
198
198
|
decimals: 9, // Default, should be configurable
|
|
@@ -201,7 +201,7 @@ export function usePrivateSwap() {
|
|
|
201
201
|
},
|
|
202
202
|
output: {
|
|
203
203
|
asset: {
|
|
204
|
-
chain: params.output.chain as
|
|
204
|
+
chain: params.output.chain as ChainId,
|
|
205
205
|
symbol: params.output.token,
|
|
206
206
|
address: null,
|
|
207
207
|
decimals: 18, // Default, should be configurable
|