@sip-protocol/sdk 0.7.3 → 0.8.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/README.md +267 -0
- package/dist/{TransportWebUSB-TQ7WZ4LE.mjs → TransportWebUSB-YQMAGJAJ.mjs} +12 -9
- package/dist/browser.d.mts +10 -4
- package/dist/browser.d.ts +10 -4
- package/dist/browser.js +47556 -19603
- package/dist/browser.mjs +628 -48
- package/dist/chunk-4GRJ5MAW.mjs +152 -0
- package/dist/chunk-5D7A3L3W.mjs +717 -0
- package/dist/chunk-64AYA5F5.mjs +7834 -0
- package/dist/chunk-GMDGB22A.mjs +379 -0
- package/dist/chunk-I534WKN7.mjs +328 -0
- package/dist/chunk-IBZVA5Y7.mjs +1003 -0
- package/dist/chunk-PRRZAWJE.mjs +223 -0
- package/dist/{chunk-UJCSKKID.mjs → chunk-XGB3TDIC.mjs} +13 -1
- package/dist/{chunk-3M3HNQCW.mjs → chunk-YWGJ77A2.mjs} +28656 -13103
- package/dist/{chunk-6WGN57S2.mjs → chunk-Z3K7W5S3.mjs} +48 -0
- package/dist/constants-LHAAUC2T.mjs +51 -0
- package/dist/dist-2OGQ7FED.mjs +3957 -0
- package/dist/dist-IFHPYLDX.mjs +254 -0
- package/dist/fulfillment_proof-ANHVPKTB.mjs +21 -0
- package/dist/funding_proof-ICFZ5LHY.mjs +21 -0
- package/dist/{index-DIBZHOOQ.d.ts → index-DXh2IGkz.d.ts} +21239 -10304
- package/dist/{index-8MQz13eJ.d.mts → index-DeE1ZzA4.d.mts} +21239 -10304
- package/dist/index.d.mts +9 -3
- package/dist/index.d.ts +9 -3
- package/dist/index.js +48396 -19623
- package/dist/index.mjs +537 -19
- package/dist/interface-Bf7w1PLW.d.mts +679 -0
- package/dist/interface-Bf7w1PLW.d.ts +679 -0
- package/dist/{noir-DKfEzWy9.d.mts → noir-kzbLVTei.d.mts} +31 -21
- package/dist/{noir-DKfEzWy9.d.ts → noir-kzbLVTei.d.ts} +31 -21
- package/dist/proofs/halo2.d.mts +151 -0
- package/dist/proofs/halo2.d.ts +151 -0
- package/dist/proofs/halo2.js +350 -0
- package/dist/proofs/halo2.mjs +11 -0
- package/dist/proofs/kimchi.d.mts +160 -0
- package/dist/proofs/kimchi.d.ts +160 -0
- package/dist/proofs/kimchi.js +431 -0
- package/dist/proofs/kimchi.mjs +13 -0
- package/dist/proofs/noir.d.mts +1 -1
- package/dist/proofs/noir.d.ts +1 -1
- package/dist/proofs/noir.js +74 -18
- package/dist/proofs/noir.mjs +84 -24
- package/dist/solana-U3MEGU7W.mjs +280 -0
- package/dist/validity_proof-3POXLPNY.mjs +21 -0
- package/package.json +44 -11
- package/src/adapters/index.ts +41 -0
- package/src/adapters/jupiter.ts +571 -0
- package/src/adapters/near-intents.ts +135 -0
- package/src/advisor/advisor.ts +653 -0
- package/src/advisor/index.ts +54 -0
- package/src/advisor/tools.ts +303 -0
- package/src/advisor/types.ts +164 -0
- package/src/chains/ethereum/announcement.ts +536 -0
- package/src/chains/ethereum/bnb-optimizations.ts +474 -0
- package/src/chains/ethereum/commitment.ts +522 -0
- package/src/chains/ethereum/constants.ts +462 -0
- package/src/chains/ethereum/deployment.ts +596 -0
- package/src/chains/ethereum/gas-estimation.ts +538 -0
- package/src/chains/ethereum/index.ts +268 -0
- package/src/chains/ethereum/optimizations.ts +614 -0
- package/src/chains/ethereum/privacy-adapter.ts +855 -0
- package/src/chains/ethereum/registry.ts +584 -0
- package/src/chains/ethereum/rpc.ts +905 -0
- package/src/chains/ethereum/stealth.ts +491 -0
- package/src/chains/ethereum/token.ts +790 -0
- package/src/chains/ethereum/transfer.ts +637 -0
- package/src/chains/ethereum/types.ts +456 -0
- package/src/chains/ethereum/viewing-key.ts +455 -0
- package/src/chains/near/commitment.ts +608 -0
- package/src/chains/near/constants.ts +284 -0
- package/src/chains/near/function-call.ts +871 -0
- package/src/chains/near/history.ts +654 -0
- package/src/chains/near/implicit-account.ts +840 -0
- package/src/chains/near/index.ts +393 -0
- package/src/chains/near/native-transfer.ts +658 -0
- package/src/chains/near/nep141.ts +775 -0
- package/src/chains/near/privacy-adapter.ts +889 -0
- package/src/chains/near/resolver.ts +971 -0
- package/src/chains/near/rpc.ts +1016 -0
- package/src/chains/near/stealth.ts +419 -0
- package/src/chains/near/types.ts +317 -0
- package/src/chains/near/viewing-key.ts +876 -0
- package/src/chains/solana/anchor-transfer.ts +386 -0
- package/src/chains/solana/commitment.ts +577 -0
- package/src/chains/solana/constants.ts +126 -12
- package/src/chains/solana/ephemeral-keys.ts +543 -0
- package/src/chains/solana/index.ts +252 -1
- package/src/chains/solana/key-derivation.ts +418 -0
- package/src/chains/solana/kit-compat.ts +334 -0
- package/src/chains/solana/optimizations.ts +560 -0
- package/src/chains/solana/privacy-adapter.ts +605 -0
- package/src/chains/solana/providers/generic.ts +47 -6
- package/src/chains/solana/providers/helius-enhanced-types.ts +336 -0
- package/src/chains/solana/providers/helius-enhanced.ts +623 -0
- package/src/chains/solana/providers/helius.ts +186 -33
- package/src/chains/solana/providers/index.ts +31 -0
- package/src/chains/solana/providers/interface.ts +61 -18
- package/src/chains/solana/providers/quicknode.ts +409 -0
- package/src/chains/solana/providers/triton.ts +426 -0
- package/src/chains/solana/providers/webhook.ts +338 -67
- package/src/chains/solana/rpc-client.ts +1150 -0
- package/src/chains/solana/scan.ts +83 -66
- package/src/chains/solana/sol-transfer.ts +732 -0
- package/src/chains/solana/spl-transfer.ts +886 -0
- package/src/chains/solana/stealth-scanner.ts +703 -0
- package/src/chains/solana/sunspot-verifier.ts +453 -0
- package/src/chains/solana/transaction-builder.ts +755 -0
- package/src/chains/solana/transfer.ts +74 -5
- package/src/chains/solana/types.ts +57 -6
- package/src/chains/solana/utils.ts +110 -0
- package/src/chains/solana/viewing-key.ts +807 -0
- package/src/compliance/fireblocks.ts +921 -0
- package/src/compliance/index.ts +23 -0
- package/src/compliance/range-sas.ts +398 -33
- package/src/config/endpoints.ts +100 -0
- package/src/crypto.ts +11 -8
- package/src/errors.ts +82 -0
- package/src/evm/erc4337-relayer.ts +830 -0
- package/src/evm/index.ts +47 -0
- package/src/fees/calculator.ts +396 -0
- package/src/fees/index.ts +87 -0
- package/src/fees/near-contract.ts +429 -0
- package/src/fees/types.ts +268 -0
- package/src/index.ts +686 -1
- package/src/intent.ts +6 -3
- package/src/logger.ts +324 -0
- package/src/network/index.ts +80 -0
- package/src/network/proxy.ts +691 -0
- package/src/optimizations/index.ts +541 -0
- package/src/oracle/types.ts +1 -0
- package/src/privacy-backends/arcium-types.ts +727 -0
- package/src/privacy-backends/arcium.ts +719 -0
- package/src/privacy-backends/combined-privacy.ts +866 -0
- package/src/privacy-backends/cspl-token.ts +595 -0
- package/src/privacy-backends/cspl-types.ts +512 -0
- package/src/privacy-backends/cspl.ts +907 -0
- package/src/privacy-backends/health.ts +488 -0
- package/src/privacy-backends/inco-types.ts +323 -0
- package/src/privacy-backends/inco.ts +616 -0
- package/src/privacy-backends/index.ts +254 -4
- package/src/privacy-backends/interface.ts +649 -6
- package/src/privacy-backends/lru-cache.ts +343 -0
- package/src/privacy-backends/magicblock.ts +458 -0
- package/src/privacy-backends/mock.ts +258 -0
- package/src/privacy-backends/privacycash.ts +13 -17
- package/src/privacy-backends/private-swap.ts +570 -0
- package/src/privacy-backends/rate-limiter.ts +683 -0
- package/src/privacy-backends/registry.ts +414 -2
- package/src/privacy-backends/router.ts +283 -3
- package/src/privacy-backends/shadowwire.ts +449 -0
- package/src/privacy-backends/sip-native.ts +3 -0
- package/src/privacy-logger.ts +191 -0
- package/src/production-safety.ts +373 -0
- package/src/proofs/aggregator.ts +1029 -0
- package/src/proofs/browser-composer.ts +1150 -0
- package/src/proofs/browser.ts +113 -25
- package/src/proofs/cache/index.ts +127 -0
- package/src/proofs/cache/interface.ts +545 -0
- package/src/proofs/cache/key-generator.ts +188 -0
- package/src/proofs/cache/lru-cache.ts +481 -0
- package/src/proofs/cache/multi-tier-cache.ts +575 -0
- package/src/proofs/cache/persistent-cache.ts +788 -0
- package/src/proofs/compliance-proof.ts +872 -0
- package/src/proofs/composer/base.ts +923 -0
- package/src/proofs/composer/index.ts +25 -0
- package/src/proofs/composer/interface.ts +518 -0
- package/src/proofs/composer/types.ts +383 -0
- package/src/proofs/converters/halo2.ts +452 -0
- package/src/proofs/converters/index.ts +208 -0
- package/src/proofs/converters/interface.ts +363 -0
- package/src/proofs/converters/kimchi.ts +462 -0
- package/src/proofs/converters/noir.ts +451 -0
- package/src/proofs/fallback.ts +888 -0
- package/src/proofs/halo2.ts +42 -0
- package/src/proofs/index.ts +471 -0
- package/src/proofs/interface.ts +13 -0
- package/src/proofs/kimchi.ts +42 -0
- package/src/proofs/lazy.ts +1004 -0
- package/src/proofs/mock.ts +25 -1
- package/src/proofs/noir.ts +110 -29
- package/src/proofs/orchestrator.ts +960 -0
- package/src/proofs/parallel/concurrency.ts +297 -0
- package/src/proofs/parallel/dependency-graph.ts +602 -0
- package/src/proofs/parallel/executor.ts +420 -0
- package/src/proofs/parallel/index.ts +131 -0
- package/src/proofs/parallel/interface.ts +685 -0
- package/src/proofs/parallel/worker-pool.ts +644 -0
- package/src/proofs/providers/halo2.ts +560 -0
- package/src/proofs/providers/index.ts +34 -0
- package/src/proofs/providers/kimchi.ts +641 -0
- package/src/proofs/validator.ts +881 -0
- package/src/proofs/verifier.ts +867 -0
- package/src/quantum/index.ts +112 -0
- package/src/quantum/winternitz-vault.ts +639 -0
- package/src/quantum/wots.ts +611 -0
- package/src/settlement/backends/direct-chain.ts +1 -0
- package/src/settlement/index.ts +9 -0
- package/src/settlement/router.ts +732 -46
- package/src/solana/index.ts +72 -0
- package/src/solana/jito-relayer.ts +687 -0
- package/src/solana/noir-verifier-types.ts +430 -0
- package/src/solana/noir-verifier.ts +816 -0
- package/src/stealth/address-derivation.ts +193 -0
- package/src/stealth/ed25519.ts +431 -0
- package/src/stealth/index.ts +233 -0
- package/src/stealth/meta-address.ts +221 -0
- package/src/stealth/secp256k1.ts +368 -0
- package/src/stealth/utils.ts +194 -0
- package/src/stealth.ts +50 -1504
- package/src/sync/index.ts +106 -0
- package/src/sync/manager.ts +504 -0
- package/src/sync/mock-provider.ts +318 -0
- package/src/sync/oblivious.ts +625 -0
- package/src/tokens/index.ts +15 -0
- package/src/tokens/registry.ts +301 -0
- package/src/utils/deprecation.ts +94 -0
- package/src/utils/index.ts +9 -0
- package/src/wallet/ethereum/index.ts +68 -0
- package/src/wallet/ethereum/metamask-privacy.ts +420 -0
- package/src/wallet/ethereum/multi-wallet.ts +646 -0
- package/src/wallet/ethereum/privacy-adapter.ts +700 -0
- package/src/wallet/ethereum/types.ts +3 -1
- package/src/wallet/ethereum/walletconnect-adapter.ts +675 -0
- package/src/wallet/hardware/index.ts +10 -0
- package/src/wallet/hardware/ledger-privacy.ts +414 -0
- package/src/wallet/index.ts +71 -0
- package/src/wallet/near/adapter.ts +626 -0
- package/src/wallet/near/index.ts +86 -0
- package/src/wallet/near/meteor-wallet.ts +1153 -0
- package/src/wallet/near/my-near-wallet.ts +790 -0
- package/src/wallet/near/wallet-selector.ts +702 -0
- package/src/wallet/solana/adapter.ts +6 -4
- package/src/wallet/solana/index.ts +13 -0
- package/src/wallet/solana/privacy-adapter.ts +567 -0
- package/src/wallet/sui/types.ts +6 -4
- package/src/zcash/rpc-client.ts +13 -6
- package/dist/chunk-2XIVXWHA.mjs +0 -1930
- package/dist/chunk-3INS3PR5.mjs +0 -884
- package/dist/chunk-3OVABDRH.mjs +0 -17096
- package/dist/chunk-7RFRWDCW.mjs +0 -1504
- package/dist/chunk-DLDWZFYC.mjs +0 -1495
- package/dist/chunk-E6SZWREQ.mjs +0 -57
- package/dist/chunk-F6F73W35.mjs +0 -16166
- package/dist/chunk-G33LB27A.mjs +0 -16166
- package/dist/chunk-HGU6HZRC.mjs +0 -231
- package/dist/chunk-L2K34JCU.mjs +0 -1496
- package/dist/chunk-OFDBEIEK.mjs +0 -16166
- package/dist/chunk-SF7YSLF5.mjs +0 -1515
- package/dist/chunk-SN4ZDTVW.mjs +0 -16166
- package/dist/chunk-WWUSGOXE.mjs +0 -17129
- package/dist/constants-VOI7BSLK.mjs +0 -27
- package/dist/index-B71aXVzk.d.ts +0 -13264
- package/dist/index-BYZbDjal.d.ts +0 -11390
- package/dist/index-CHB3KuOB.d.mts +0 -11859
- package/dist/index-CzWPI6Le.d.ts +0 -11859
- package/dist/index-pOIIuwfV.d.mts +0 -13264
- package/dist/index-xbWjohNq.d.mts +0 -11390
- package/dist/solana-4O4K45VU.mjs +0 -46
- package/dist/solana-5EMCTPTS.mjs +0 -46
- package/dist/solana-NDABAZ6P.mjs +0 -56
- package/dist/solana-Q4NAVBTS.mjs +0 -46
- package/dist/solana-ZYO63LY5.mjs +0 -46
|
@@ -0,0 +1,653 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Privacy Advisor Agent
|
|
3
|
+
*
|
|
4
|
+
* LangChain-powered AI agent that analyzes wallet privacy and provides
|
|
5
|
+
* intelligent, contextual recommendations in plain English.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { ChatOpenAI } from '@langchain/openai'
|
|
11
|
+
import { HumanMessage, SystemMessage, AIMessage } from '@langchain/core/messages'
|
|
12
|
+
import { StringOutputParser } from '@langchain/core/output_parsers'
|
|
13
|
+
import { z } from 'zod'
|
|
14
|
+
|
|
15
|
+
import type {
|
|
16
|
+
PrivacyAdvisorConfig,
|
|
17
|
+
AdvisoryContext,
|
|
18
|
+
AdvisorResponse,
|
|
19
|
+
PrivacyAdvisoryReport,
|
|
20
|
+
AdvisorRecommendation,
|
|
21
|
+
AdvisorMessage,
|
|
22
|
+
StreamCallback,
|
|
23
|
+
} from './types'
|
|
24
|
+
import type { FullAnalysisResult, RiskLevel } from '../surveillance/types'
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* System prompt for the Privacy Advisor Agent
|
|
28
|
+
*/
|
|
29
|
+
const SYSTEM_PROMPT = `You are a Privacy Advisor for SIP Protocol, the privacy standard for Web3. Your role is to help users understand their wallet's privacy exposure and provide actionable recommendations.
|
|
30
|
+
|
|
31
|
+
## Your Principles:
|
|
32
|
+
1. **Clarity**: Explain complex privacy concepts in plain English
|
|
33
|
+
2. **Actionability**: Every recommendation should have clear, step-by-step actions
|
|
34
|
+
3. **Prioritization**: Focus on highest-impact improvements first
|
|
35
|
+
4. **Education**: Help users understand WHY something matters, not just WHAT to do
|
|
36
|
+
5. **Honesty**: Be direct about risks without causing unnecessary alarm
|
|
37
|
+
|
|
38
|
+
## Privacy Score Categories (100 points total):
|
|
39
|
+
- Address Reuse (0-25 points): Reusing addresses links your transactions
|
|
40
|
+
- Cluster Exposure (0-25 points): Common-input heuristic can link your wallets
|
|
41
|
+
- Exchange Exposure (0-20 points): CEX interactions create KYC-linked records
|
|
42
|
+
- Temporal Patterns (0-15 points): Regular timing reveals timezone/habits
|
|
43
|
+
- Social Links (0-15 points): ENS/SNS domains link identity to wallet
|
|
44
|
+
|
|
45
|
+
## Risk Levels:
|
|
46
|
+
- Critical (0-25): Severe privacy exposure, immediate action needed
|
|
47
|
+
- High (26-50): Significant risks, prioritize improvements
|
|
48
|
+
- Medium (51-75): Moderate exposure, room for improvement
|
|
49
|
+
- Low (76-100): Good privacy hygiene, maintain practices
|
|
50
|
+
|
|
51
|
+
## SIP Protocol Benefits:
|
|
52
|
+
- Stealth Addresses: One-time addresses prevent transaction linking
|
|
53
|
+
- Pedersen Commitments: Hide transaction amounts cryptographically
|
|
54
|
+
- Viewing Keys: Selective disclosure for compliance without sacrificing privacy
|
|
55
|
+
|
|
56
|
+
## Response Guidelines:
|
|
57
|
+
- Use bullet points and numbered lists for clarity
|
|
58
|
+
- Include specific, actionable steps
|
|
59
|
+
- Estimate time/difficulty for each recommendation
|
|
60
|
+
- Highlight what SIP Protocol can automate
|
|
61
|
+
- Suggest 2-3 follow-up questions to explore further`
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Schema for structured report generation
|
|
65
|
+
*/
|
|
66
|
+
const ReportSchema = z.object({
|
|
67
|
+
summary: z.string().describe('2-3 sentence executive summary'),
|
|
68
|
+
recommendations: z.array(z.object({
|
|
69
|
+
id: z.string(),
|
|
70
|
+
priority: z.number().min(1).max(10),
|
|
71
|
+
title: z.string(),
|
|
72
|
+
explanation: z.string(),
|
|
73
|
+
actions: z.array(z.string()),
|
|
74
|
+
expectedImprovement: z.number(),
|
|
75
|
+
difficulty: z.enum(['easy', 'medium', 'hard']),
|
|
76
|
+
estimatedTime: z.string(),
|
|
77
|
+
canAutomate: z.boolean(),
|
|
78
|
+
})),
|
|
79
|
+
keyRisks: z.array(z.object({
|
|
80
|
+
category: z.string(),
|
|
81
|
+
description: z.string(),
|
|
82
|
+
severity: z.enum(['critical', 'high', 'medium', 'low']),
|
|
83
|
+
})),
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* PrivacyAdvisorAgent - AI-powered privacy recommendations
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```typescript
|
|
91
|
+
* import { PrivacyAdvisorAgent, createSurveillanceAnalyzer } from '@sip-protocol/sdk'
|
|
92
|
+
*
|
|
93
|
+
* const analyzer = createSurveillanceAnalyzer({
|
|
94
|
+
* heliusApiKey: process.env.HELIUS_API_KEY!,
|
|
95
|
+
* })
|
|
96
|
+
*
|
|
97
|
+
* const advisor = new PrivacyAdvisorAgent({
|
|
98
|
+
* openaiApiKey: process.env.OPENAI_API_KEY!,
|
|
99
|
+
* })
|
|
100
|
+
*
|
|
101
|
+
* const analysis = await analyzer.analyze('7xK9...')
|
|
102
|
+
* const response = await advisor.analyze({
|
|
103
|
+
* analysisResult: analysis,
|
|
104
|
+
* userQuery: 'What should I do first to improve my privacy?',
|
|
105
|
+
* })
|
|
106
|
+
*
|
|
107
|
+
* console.log(response.message)
|
|
108
|
+
* console.log(response.report?.recommendations)
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
export class PrivacyAdvisorAgent {
|
|
112
|
+
private model: ChatOpenAI
|
|
113
|
+
private config: Required<PrivacyAdvisorConfig>
|
|
114
|
+
private conversationHistory: AdvisorMessage[] = []
|
|
115
|
+
|
|
116
|
+
constructor(config: PrivacyAdvisorConfig) {
|
|
117
|
+
if (!config.openaiApiKey) {
|
|
118
|
+
throw new Error(
|
|
119
|
+
'OpenAI API key is required. Get one at https://platform.openai.com'
|
|
120
|
+
)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
this.config = {
|
|
124
|
+
openaiApiKey: config.openaiApiKey,
|
|
125
|
+
model: config.model ?? 'gpt-4o-mini',
|
|
126
|
+
temperature: config.temperature ?? 0.3,
|
|
127
|
+
maxTokens: config.maxTokens ?? 1024,
|
|
128
|
+
verbose: config.verbose ?? false,
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
this.model = new ChatOpenAI({
|
|
132
|
+
openAIApiKey: this.config.openaiApiKey,
|
|
133
|
+
modelName: this.config.model,
|
|
134
|
+
temperature: this.config.temperature,
|
|
135
|
+
maxTokens: this.config.maxTokens,
|
|
136
|
+
})
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Analyze wallet privacy and generate recommendations
|
|
141
|
+
*
|
|
142
|
+
* @param context - Analysis context including surveillance results
|
|
143
|
+
* @returns Advisor response with message and optional report
|
|
144
|
+
*/
|
|
145
|
+
async analyze(context: AdvisoryContext): Promise<AdvisorResponse> {
|
|
146
|
+
const { analysisResult, userQuery, preferences } = context
|
|
147
|
+
|
|
148
|
+
// Build the analysis prompt
|
|
149
|
+
const analysisPrompt = this.buildAnalysisPrompt(analysisResult, preferences)
|
|
150
|
+
|
|
151
|
+
// Prepare messages
|
|
152
|
+
const messages = [
|
|
153
|
+
new SystemMessage(SYSTEM_PROMPT),
|
|
154
|
+
new HumanMessage(analysisPrompt),
|
|
155
|
+
]
|
|
156
|
+
|
|
157
|
+
// Add conversation history if present
|
|
158
|
+
if (context.conversationHistory) {
|
|
159
|
+
for (const msg of context.conversationHistory) {
|
|
160
|
+
if (msg.role === 'user') {
|
|
161
|
+
messages.push(new HumanMessage(msg.content))
|
|
162
|
+
} else if (msg.role === 'assistant') {
|
|
163
|
+
messages.push(new AIMessage(msg.content))
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Add user query if present
|
|
169
|
+
if (userQuery) {
|
|
170
|
+
messages.push(new HumanMessage(userQuery))
|
|
171
|
+
} else {
|
|
172
|
+
messages.push(new HumanMessage(
|
|
173
|
+
'Please analyze this wallet and provide a comprehensive privacy report with prioritized recommendations.'
|
|
174
|
+
))
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Generate response
|
|
178
|
+
const response = await this.model.invoke(messages)
|
|
179
|
+
const parser = new StringOutputParser()
|
|
180
|
+
const content = await parser.invoke(response)
|
|
181
|
+
|
|
182
|
+
// Track usage
|
|
183
|
+
const usage = response.usage_metadata ? {
|
|
184
|
+
promptTokens: response.usage_metadata.input_tokens,
|
|
185
|
+
completionTokens: response.usage_metadata.output_tokens,
|
|
186
|
+
totalTokens: response.usage_metadata.total_tokens,
|
|
187
|
+
estimatedCost: this.estimateCost(
|
|
188
|
+
response.usage_metadata.input_tokens,
|
|
189
|
+
response.usage_metadata.output_tokens
|
|
190
|
+
),
|
|
191
|
+
} : undefined
|
|
192
|
+
|
|
193
|
+
// Generate structured report
|
|
194
|
+
const report = this.generateReport(analysisResult, content)
|
|
195
|
+
|
|
196
|
+
// Generate suggested follow-up questions
|
|
197
|
+
const suggestedQuestions = this.generateSuggestedQuestions(analysisResult)
|
|
198
|
+
|
|
199
|
+
// Update conversation history
|
|
200
|
+
this.conversationHistory.push(
|
|
201
|
+
{ role: 'user', content: userQuery || 'Analyze my wallet privacy', timestamp: Date.now() },
|
|
202
|
+
{ role: 'assistant', content, timestamp: Date.now() }
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
return {
|
|
206
|
+
message: content,
|
|
207
|
+
report,
|
|
208
|
+
suggestedQuestions,
|
|
209
|
+
usage,
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Chat with the advisor about privacy (follow-up questions)
|
|
215
|
+
*
|
|
216
|
+
* @param message - User message
|
|
217
|
+
* @param context - Optional analysis context for new analysis
|
|
218
|
+
* @returns Advisor response
|
|
219
|
+
*/
|
|
220
|
+
async chat(message: string, context?: AdvisoryContext): Promise<AdvisorResponse> {
|
|
221
|
+
const messages = [new SystemMessage(SYSTEM_PROMPT)]
|
|
222
|
+
|
|
223
|
+
// Add analysis context if provided
|
|
224
|
+
if (context?.analysisResult) {
|
|
225
|
+
const analysisPrompt = this.buildAnalysisPrompt(
|
|
226
|
+
context.analysisResult,
|
|
227
|
+
context.preferences
|
|
228
|
+
)
|
|
229
|
+
messages.push(new HumanMessage(analysisPrompt))
|
|
230
|
+
messages.push(new AIMessage('I\'ve analyzed the wallet data. What would you like to know?'))
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Add conversation history
|
|
234
|
+
for (const msg of this.conversationHistory) {
|
|
235
|
+
if (msg.role === 'user') {
|
|
236
|
+
messages.push(new HumanMessage(msg.content))
|
|
237
|
+
} else if (msg.role === 'assistant') {
|
|
238
|
+
messages.push(new AIMessage(msg.content))
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Add current message
|
|
243
|
+
messages.push(new HumanMessage(message))
|
|
244
|
+
|
|
245
|
+
// Generate response
|
|
246
|
+
const response = await this.model.invoke(messages)
|
|
247
|
+
const parser = new StringOutputParser()
|
|
248
|
+
const content = await parser.invoke(response)
|
|
249
|
+
|
|
250
|
+
// Track usage
|
|
251
|
+
const usage = response.usage_metadata ? {
|
|
252
|
+
promptTokens: response.usage_metadata.input_tokens,
|
|
253
|
+
completionTokens: response.usage_metadata.output_tokens,
|
|
254
|
+
totalTokens: response.usage_metadata.total_tokens,
|
|
255
|
+
estimatedCost: this.estimateCost(
|
|
256
|
+
response.usage_metadata.input_tokens,
|
|
257
|
+
response.usage_metadata.output_tokens
|
|
258
|
+
),
|
|
259
|
+
} : undefined
|
|
260
|
+
|
|
261
|
+
// Update conversation history
|
|
262
|
+
this.conversationHistory.push(
|
|
263
|
+
{ role: 'user', content: message, timestamp: Date.now() },
|
|
264
|
+
{ role: 'assistant', content, timestamp: Date.now() }
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
return {
|
|
268
|
+
message: content,
|
|
269
|
+
usage,
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Stream a response for real-time UI updates
|
|
275
|
+
*
|
|
276
|
+
* @param context - Analysis context
|
|
277
|
+
* @param onChunk - Callback for each streamed chunk
|
|
278
|
+
* @returns Final advisor response
|
|
279
|
+
*/
|
|
280
|
+
async stream(
|
|
281
|
+
context: AdvisoryContext,
|
|
282
|
+
onChunk: StreamCallback
|
|
283
|
+
): Promise<AdvisorResponse> {
|
|
284
|
+
const { analysisResult, userQuery, preferences } = context
|
|
285
|
+
|
|
286
|
+
// Build the analysis prompt
|
|
287
|
+
const analysisPrompt = this.buildAnalysisPrompt(analysisResult, preferences)
|
|
288
|
+
|
|
289
|
+
// Prepare messages
|
|
290
|
+
const messages = [
|
|
291
|
+
new SystemMessage(SYSTEM_PROMPT),
|
|
292
|
+
new HumanMessage(analysisPrompt),
|
|
293
|
+
]
|
|
294
|
+
|
|
295
|
+
if (userQuery) {
|
|
296
|
+
messages.push(new HumanMessage(userQuery))
|
|
297
|
+
} else {
|
|
298
|
+
messages.push(new HumanMessage(
|
|
299
|
+
'Please analyze this wallet and provide a comprehensive privacy report with prioritized recommendations.'
|
|
300
|
+
))
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// Stream response
|
|
304
|
+
let fullContent = ''
|
|
305
|
+
const stream = await this.model.stream(messages)
|
|
306
|
+
|
|
307
|
+
for await (const chunk of stream) {
|
|
308
|
+
const text = typeof chunk.content === 'string' ? chunk.content : ''
|
|
309
|
+
fullContent += text
|
|
310
|
+
onChunk(text)
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Generate report from full content
|
|
314
|
+
const report = this.generateReport(analysisResult, fullContent)
|
|
315
|
+
const suggestedQuestions = this.generateSuggestedQuestions(analysisResult)
|
|
316
|
+
|
|
317
|
+
// Update conversation history
|
|
318
|
+
this.conversationHistory.push(
|
|
319
|
+
{ role: 'user', content: userQuery || 'Analyze my wallet privacy', timestamp: Date.now() },
|
|
320
|
+
{ role: 'assistant', content: fullContent, timestamp: Date.now() }
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
return {
|
|
324
|
+
message: fullContent,
|
|
325
|
+
report,
|
|
326
|
+
suggestedQuestions,
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Clear conversation history
|
|
332
|
+
*/
|
|
333
|
+
clearHistory(): void {
|
|
334
|
+
this.conversationHistory = []
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Get conversation history
|
|
339
|
+
*/
|
|
340
|
+
getHistory(): AdvisorMessage[] {
|
|
341
|
+
return [...this.conversationHistory]
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Build analysis prompt from surveillance data
|
|
346
|
+
*/
|
|
347
|
+
private buildAnalysisPrompt(
|
|
348
|
+
result: FullAnalysisResult,
|
|
349
|
+
preferences?: AdvisoryContext['preferences']
|
|
350
|
+
): string {
|
|
351
|
+
const { privacyScore, addressReuse, cluster, exchangeExposure, temporalPatterns, socialLinks, sipComparison } = result
|
|
352
|
+
|
|
353
|
+
let prompt = `## Wallet Privacy Analysis Data
|
|
354
|
+
|
|
355
|
+
**Wallet**: ${privacyScore.walletAddress}
|
|
356
|
+
**Overall Score**: ${privacyScore.overall}/100
|
|
357
|
+
**Risk Level**: ${privacyScore.risk.toUpperCase()}
|
|
358
|
+
**Transactions Analyzed**: ${result.transactionCount}
|
|
359
|
+
|
|
360
|
+
### Score Breakdown:
|
|
361
|
+
- Address Reuse: ${privacyScore.breakdown.addressReuse}/25 points
|
|
362
|
+
- Cluster Exposure: ${privacyScore.breakdown.clusterExposure}/25 points
|
|
363
|
+
- Exchange Exposure: ${privacyScore.breakdown.exchangeExposure}/20 points
|
|
364
|
+
- Temporal Patterns: ${privacyScore.breakdown.temporalPatterns}/15 points
|
|
365
|
+
- Social Links: ${privacyScore.breakdown.socialLinks}/15 points
|
|
366
|
+
|
|
367
|
+
### Detailed Findings:
|
|
368
|
+
|
|
369
|
+
**Address Reuse**:
|
|
370
|
+
- Receive reuse count: ${addressReuse.receiveReuseCount}
|
|
371
|
+
- Send reuse count: ${addressReuse.sendReuseCount}
|
|
372
|
+
- Total reuse: ${addressReuse.totalReuseCount}
|
|
373
|
+
- Score deduction: -${addressReuse.scoreDeduction} points
|
|
374
|
+
|
|
375
|
+
**Cluster Detection (CIOH)**:
|
|
376
|
+
- Linked addresses found: ${cluster.linkedAddressCount}
|
|
377
|
+
- Confidence: ${(cluster.confidence * 100).toFixed(0)}%
|
|
378
|
+
- Clusters detected: ${cluster.clusters.length}
|
|
379
|
+
- Score deduction: -${cluster.scoreDeduction} points
|
|
380
|
+
|
|
381
|
+
**Exchange Exposure**:
|
|
382
|
+
- Exchanges interacted: ${exchangeExposure.exchangeCount}
|
|
383
|
+
- Total deposits: ${exchangeExposure.depositCount}
|
|
384
|
+
- Total withdrawals: ${exchangeExposure.withdrawalCount}
|
|
385
|
+
- Score deduction: -${exchangeExposure.scoreDeduction} points
|
|
386
|
+
${exchangeExposure.exchanges.length > 0 ? `- Exchanges: ${exchangeExposure.exchanges.map(e => `${e.name} (${e.type}, KYC: ${e.kycRequired})`).join(', ')}` : ''}
|
|
387
|
+
|
|
388
|
+
**Temporal Patterns**:
|
|
389
|
+
- Patterns detected: ${temporalPatterns.patterns.length}
|
|
390
|
+
${temporalPatterns.inferredTimezone ? `- Inferred timezone: ${temporalPatterns.inferredTimezone}` : ''}
|
|
391
|
+
- Score deduction: -${temporalPatterns.scoreDeduction} points
|
|
392
|
+
|
|
393
|
+
**Social Links**:
|
|
394
|
+
- Is doxxed: ${socialLinks.isDoxxed ? 'YES' : 'No'}
|
|
395
|
+
- Partial exposure: ${socialLinks.partialExposure ? 'Yes' : 'No'}
|
|
396
|
+
- Links found: ${socialLinks.links.length}
|
|
397
|
+
- Score deduction: -${socialLinks.scoreDeduction} points
|
|
398
|
+
|
|
399
|
+
### SIP Protocol Projection:
|
|
400
|
+
- Current score: ${sipComparison.currentScore}/100
|
|
401
|
+
- Projected with SIP: ${sipComparison.projectedScore}/100
|
|
402
|
+
- Potential improvement: +${sipComparison.improvement} points`
|
|
403
|
+
|
|
404
|
+
// Add user preferences if specified
|
|
405
|
+
if (preferences) {
|
|
406
|
+
prompt += '\n\n### User Preferences:'
|
|
407
|
+
if (preferences.preferAutomation) {
|
|
408
|
+
prompt += '\n- Prefers automated solutions over manual steps'
|
|
409
|
+
}
|
|
410
|
+
if (preferences.technicalLevel) {
|
|
411
|
+
prompt += `\n- Technical level: ${preferences.technicalLevel}`
|
|
412
|
+
}
|
|
413
|
+
if (preferences.focusAreas?.length) {
|
|
414
|
+
prompt += `\n- Focus areas: ${preferences.focusAreas.join(', ')}`
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
return prompt
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Generate structured report from analysis and LLM response
|
|
423
|
+
*/
|
|
424
|
+
private generateReport(
|
|
425
|
+
result: FullAnalysisResult,
|
|
426
|
+
llmResponse: string
|
|
427
|
+
): PrivacyAdvisoryReport {
|
|
428
|
+
const { privacyScore, sipComparison } = result
|
|
429
|
+
|
|
430
|
+
// Extract recommendations from existing privacy score
|
|
431
|
+
const recommendations: AdvisorRecommendation[] = privacyScore.recommendations
|
|
432
|
+
.slice(0, 5)
|
|
433
|
+
.map((rec, index) => ({
|
|
434
|
+
id: rec.id,
|
|
435
|
+
priority: index + 1,
|
|
436
|
+
title: rec.title,
|
|
437
|
+
explanation: rec.description,
|
|
438
|
+
actions: [rec.action],
|
|
439
|
+
expectedImprovement: rec.potentialGain,
|
|
440
|
+
difficulty: this.mapSeverityToDifficulty(rec.severity),
|
|
441
|
+
estimatedTime: this.estimateTime(rec.category),
|
|
442
|
+
canAutomate: this.canAutomate(rec.category),
|
|
443
|
+
}))
|
|
444
|
+
|
|
445
|
+
// Extract key risks
|
|
446
|
+
const keyRisks = this.extractKeyRisks(result)
|
|
447
|
+
|
|
448
|
+
// Generate summary from LLM response (first 2-3 sentences)
|
|
449
|
+
const summaryMatch = llmResponse.match(/^(.+?\..*?\..*?\.)/s)
|
|
450
|
+
const summary = summaryMatch
|
|
451
|
+
? summaryMatch[1].replace(/\n/g, ' ').trim()
|
|
452
|
+
: `Your wallet has a privacy score of ${privacyScore.overall}/100 (${privacyScore.risk} risk). ${
|
|
453
|
+
privacyScore.recommendations[0]
|
|
454
|
+
? `Top priority: ${privacyScore.recommendations[0].title}.`
|
|
455
|
+
: 'Review the recommendations below to improve your privacy.'
|
|
456
|
+
}`
|
|
457
|
+
|
|
458
|
+
return {
|
|
459
|
+
walletAddress: privacyScore.walletAddress,
|
|
460
|
+
currentScore: privacyScore.overall,
|
|
461
|
+
riskLevel: privacyScore.risk,
|
|
462
|
+
summary,
|
|
463
|
+
recommendations,
|
|
464
|
+
keyRisks,
|
|
465
|
+
sipBenefits: {
|
|
466
|
+
projectedScore: sipComparison.projectedScore,
|
|
467
|
+
improvement: sipComparison.improvement,
|
|
468
|
+
features: [
|
|
469
|
+
'Stealth addresses for unlinkable transactions',
|
|
470
|
+
'Pedersen commitments for hidden amounts',
|
|
471
|
+
'Viewing keys for selective compliance disclosure',
|
|
472
|
+
],
|
|
473
|
+
},
|
|
474
|
+
generatedAt: Date.now(),
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* Extract key risks from analysis
|
|
480
|
+
*/
|
|
481
|
+
private extractKeyRisks(result: FullAnalysisResult): PrivacyAdvisoryReport['keyRisks'] {
|
|
482
|
+
const risks: PrivacyAdvisoryReport['keyRisks'] = []
|
|
483
|
+
|
|
484
|
+
if (result.addressReuse.scoreDeduction > 10) {
|
|
485
|
+
risks.push({
|
|
486
|
+
category: 'Address Reuse',
|
|
487
|
+
description: `Found ${result.addressReuse.totalReuseCount} instances of address reuse, allowing observers to link your transactions together.`,
|
|
488
|
+
severity: result.addressReuse.scoreDeduction > 20 ? 'critical' : 'high',
|
|
489
|
+
})
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
if (result.cluster.linkedAddressCount > 0) {
|
|
493
|
+
risks.push({
|
|
494
|
+
category: 'Wallet Clustering',
|
|
495
|
+
description: `${result.cluster.linkedAddressCount} addresses are linked to your wallet through common-input heuristics.`,
|
|
496
|
+
severity: result.cluster.scoreDeduction > 15 ? 'high' : 'medium',
|
|
497
|
+
})
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
if (result.exchangeExposure.exchangeCount > 0) {
|
|
501
|
+
const kycExchanges = result.exchangeExposure.exchanges.filter(e => e.kycRequired)
|
|
502
|
+
if (kycExchanges.length > 0) {
|
|
503
|
+
risks.push({
|
|
504
|
+
category: 'Exchange Exposure',
|
|
505
|
+
description: `Interacted with ${kycExchanges.length} KYC-required exchange(s), creating a link between your identity and on-chain activity.`,
|
|
506
|
+
severity: kycExchanges.length > 2 ? 'high' : 'medium',
|
|
507
|
+
})
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
if (result.socialLinks.isDoxxed) {
|
|
512
|
+
risks.push({
|
|
513
|
+
category: 'Identity Exposure',
|
|
514
|
+
description: 'Your wallet is publicly linked to your identity through social profiles or naming services.',
|
|
515
|
+
severity: 'critical',
|
|
516
|
+
})
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
if (result.temporalPatterns.patterns.length > 0) {
|
|
520
|
+
risks.push({
|
|
521
|
+
category: 'Behavioral Patterns',
|
|
522
|
+
description: `Detected ${result.temporalPatterns.patterns.length} timing pattern(s) that could reveal your timezone or habits.`,
|
|
523
|
+
severity: 'low',
|
|
524
|
+
})
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
return risks
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* Generate suggested follow-up questions
|
|
532
|
+
*/
|
|
533
|
+
private generateSuggestedQuestions(result: FullAnalysisResult): string[] {
|
|
534
|
+
const questions: string[] = []
|
|
535
|
+
|
|
536
|
+
if (result.privacyScore.overall < 50) {
|
|
537
|
+
questions.push('What\'s the single most impactful thing I can do right now?')
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
if (result.exchangeExposure.exchangeCount > 0) {
|
|
541
|
+
questions.push('How can I reduce my exchange exposure going forward?')
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
if (result.addressReuse.totalReuseCount > 5) {
|
|
545
|
+
questions.push('How do stealth addresses prevent address reuse?')
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
questions.push('How would using SIP Protocol improve my privacy?')
|
|
549
|
+
questions.push('What privacy practices should I adopt for the future?')
|
|
550
|
+
|
|
551
|
+
return questions.slice(0, 3)
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
/**
|
|
555
|
+
* Map severity to difficulty
|
|
556
|
+
*/
|
|
557
|
+
private mapSeverityToDifficulty(severity: RiskLevel): 'easy' | 'medium' | 'hard' {
|
|
558
|
+
switch (severity) {
|
|
559
|
+
case 'critical':
|
|
560
|
+
case 'high':
|
|
561
|
+
return 'medium'
|
|
562
|
+
case 'medium':
|
|
563
|
+
return 'easy'
|
|
564
|
+
case 'low':
|
|
565
|
+
return 'easy'
|
|
566
|
+
default:
|
|
567
|
+
return 'medium'
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/**
|
|
572
|
+
* Estimate time to implement recommendation
|
|
573
|
+
*/
|
|
574
|
+
private estimateTime(category: string): string {
|
|
575
|
+
switch (category) {
|
|
576
|
+
case 'addressReuse':
|
|
577
|
+
return '5-10 minutes'
|
|
578
|
+
case 'clusterExposure':
|
|
579
|
+
return '15-30 minutes'
|
|
580
|
+
case 'exchangeExposure':
|
|
581
|
+
return '1-2 hours'
|
|
582
|
+
case 'temporalPatterns':
|
|
583
|
+
return 'Ongoing practice'
|
|
584
|
+
case 'socialLinks':
|
|
585
|
+
return '30-60 minutes'
|
|
586
|
+
default:
|
|
587
|
+
return '10-20 minutes'
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
/**
|
|
592
|
+
* Check if SIP can automate this recommendation
|
|
593
|
+
*/
|
|
594
|
+
private canAutomate(category: string): boolean {
|
|
595
|
+
switch (category) {
|
|
596
|
+
case 'addressReuse':
|
|
597
|
+
return true // Stealth addresses
|
|
598
|
+
case 'clusterExposure':
|
|
599
|
+
return true // Stealth addresses prevent clustering
|
|
600
|
+
case 'exchangeExposure':
|
|
601
|
+
return false // User behavior
|
|
602
|
+
case 'temporalPatterns':
|
|
603
|
+
return false // User behavior
|
|
604
|
+
case 'socialLinks':
|
|
605
|
+
return false // User decision
|
|
606
|
+
default:
|
|
607
|
+
return false
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
/**
|
|
612
|
+
* Estimate cost based on model and token usage
|
|
613
|
+
*/
|
|
614
|
+
private estimateCost(inputTokens: number, outputTokens: number): number {
|
|
615
|
+
// Pricing as of 2024 (in USD per 1K tokens)
|
|
616
|
+
const pricing: Record<string, { input: number; output: number }> = {
|
|
617
|
+
'gpt-4o-mini': { input: 0.00015, output: 0.0006 },
|
|
618
|
+
'gpt-4o': { input: 0.005, output: 0.015 },
|
|
619
|
+
'gpt-4-turbo': { input: 0.01, output: 0.03 },
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
const modelPricing = pricing[this.config.model] ?? pricing['gpt-4o-mini']
|
|
623
|
+
|
|
624
|
+
return (
|
|
625
|
+
(inputTokens / 1000) * modelPricing.input +
|
|
626
|
+
(outputTokens / 1000) * modelPricing.output
|
|
627
|
+
)
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
/**
|
|
632
|
+
* Create a new PrivacyAdvisorAgent instance
|
|
633
|
+
*
|
|
634
|
+
* @param config - Agent configuration
|
|
635
|
+
* @returns PrivacyAdvisorAgent instance
|
|
636
|
+
*
|
|
637
|
+
* @example
|
|
638
|
+
* ```typescript
|
|
639
|
+
* const advisor = createPrivacyAdvisor({
|
|
640
|
+
* openaiApiKey: 'your-api-key',
|
|
641
|
+
* model: 'gpt-4o-mini', // Cost-efficient default
|
|
642
|
+
* })
|
|
643
|
+
*
|
|
644
|
+
* const response = await advisor.analyze({
|
|
645
|
+
* analysisResult: await analyzer.analyze('wallet-address'),
|
|
646
|
+
* })
|
|
647
|
+
* ```
|
|
648
|
+
*/
|
|
649
|
+
export function createPrivacyAdvisor(
|
|
650
|
+
config: PrivacyAdvisorConfig
|
|
651
|
+
): PrivacyAdvisorAgent {
|
|
652
|
+
return new PrivacyAdvisorAgent(config)
|
|
653
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Privacy Advisor Module
|
|
3
|
+
*
|
|
4
|
+
* LangChain-powered AI agent for intelligent privacy recommendations.
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { PrivacyAdvisorAgent, createPrivacyAdvisorTools } from '@sip-protocol/sdk'
|
|
11
|
+
*
|
|
12
|
+
* // Create advisor (simple chat mode)
|
|
13
|
+
* const advisor = new PrivacyAdvisorAgent({
|
|
14
|
+
* openaiApiKey: process.env.OPENAI_API_KEY!,
|
|
15
|
+
* })
|
|
16
|
+
*
|
|
17
|
+
* // Or use tools for a full agent
|
|
18
|
+
* const tools = createPrivacyAdvisorTools({
|
|
19
|
+
* heliusApiKey: process.env.HELIUS_API_KEY!,
|
|
20
|
+
* })
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
// Main agent
|
|
25
|
+
export { PrivacyAdvisorAgent, createPrivacyAdvisor } from './advisor'
|
|
26
|
+
|
|
27
|
+
// LangChain tools (for building custom agents)
|
|
28
|
+
export {
|
|
29
|
+
createPrivacyAdvisorTools,
|
|
30
|
+
createAnalyzeWalletTool,
|
|
31
|
+
createQuickScoreTool,
|
|
32
|
+
createSIPComparisonTool,
|
|
33
|
+
createExplainTool,
|
|
34
|
+
} from './tools'
|
|
35
|
+
|
|
36
|
+
export type { ToolsConfig } from './tools'
|
|
37
|
+
|
|
38
|
+
// Types
|
|
39
|
+
export type {
|
|
40
|
+
// Core types
|
|
41
|
+
AdvisorRole,
|
|
42
|
+
AdvisorMessage,
|
|
43
|
+
AdvisorStatus,
|
|
44
|
+
// Configuration
|
|
45
|
+
PrivacyAdvisorConfig,
|
|
46
|
+
AdvisoryContext,
|
|
47
|
+
// Response types
|
|
48
|
+
AdvisorResponse,
|
|
49
|
+
PrivacyAdvisoryReport,
|
|
50
|
+
AdvisorRecommendation,
|
|
51
|
+
// Utilities
|
|
52
|
+
ToolResult,
|
|
53
|
+
StreamCallback,
|
|
54
|
+
} from './types'
|