@hexora/address-guard 1.0.0 → 1.0.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/LICENSE +21 -0
- package/README.md +495 -0
- package/package.json +3 -2
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Daniil Sapielkin
|
|
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.
|
package/README.md
ADDED
|
@@ -0,0 +1,495 @@
|
|
|
1
|
+
# HEXORA
|
|
2
|
+
|
|
3
|
+
**Web3 Security SDK** — detects address poisoning attacks before users lose funds.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/hexora)
|
|
6
|
+
[](https://bundlephobia.com/package/hexora)
|
|
7
|
+
[](./LICENSE)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## The Problem
|
|
12
|
+
|
|
13
|
+
Address poisoning attacks cost millions every year. An attacker creates a wallet with the same first and last characters as a legitimate address, sends a tiny transaction to the victim, and waits for them to copy the wrong address from their history.
|
|
14
|
+
|
|
15
|
+
**MetaMask, Trust Wallet, Ledger Live** — none of them detect this. HEXORA fills that gap at the SDK level.
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
Legit: 0xEF70efAf74A3caAbF254E786F834133864BC80E6
|
|
19
|
+
Fake: 0xe7d40975DD0396Fc81A39b0ED1f2b7aCE1BC80E6
|
|
20
|
+
^^^^^ different middle ^^^^^
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
These are real addresses from a live attack on BNB Chain. The victim `0x7265BD...075a91` had `0xEF70ef...BC80E6` in their history — the attacker deployed `0xe7d409...BC80E6` with matching first and last 4 chars and sent a [zero-value transfer](https://bscscan.com/tx/0x67e2b135f1255fa45db213d2da8231331c5b3c681031553b17e543bc7292acc8) to poison the history.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
### Real case
|
|
28
|
+
|
|
29
|
+
https://x.com/incrypted/status/2029865814342398139
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Install
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npm install hexora
|
|
37
|
+
# or
|
|
38
|
+
pnpm add hexora
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Quick Start
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
import { checkAddress } from "hexora";
|
|
47
|
+
|
|
48
|
+
const result = await checkAddress({
|
|
49
|
+
userAddress: "0x...", // connected wallet
|
|
50
|
+
inputAddress: "0x...", // address the user is about to send to
|
|
51
|
+
provider: window.ethereum,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
if (result.scam) {
|
|
55
|
+
console.warn(result.reason); // "batch_poisoning"
|
|
56
|
+
console.warn(result.riskLevel); // "critical"
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## How It Works
|
|
63
|
+
|
|
64
|
+
Every `checkAddress()` call runs through a multi-layer pipeline:
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
1. Provider Detection — auto-detects MetaMask / WalletConnect / Phantom / any EIP-1193
|
|
68
|
+
2. Chain Resolution — reads chainId from provider, no manual chain param needed
|
|
69
|
+
3. History Fetch — fetches last N transactions for both addresses in parallel
|
|
70
|
+
4. Similarity Check — weighted prefix/suffix/Levenshtein comparison
|
|
71
|
+
5. Poison Detection — zero-value transfers, batch poisoning, transferFrom spoofing, dust
|
|
72
|
+
6. Input Addr Analysis — checks if inputAddress itself is a known attacker wallet
|
|
73
|
+
7. Risk Scoring — combines all signals into a final structured result
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Response
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
{
|
|
82
|
+
scam: true,
|
|
83
|
+
reason: "zero_value_transfer",
|
|
84
|
+
riskLevel: "critical",
|
|
85
|
+
similarityScore: 87,
|
|
86
|
+
confidence: 96,
|
|
87
|
+
matchedAddress: "0xEF70efAf74A3caAbF254E786F834133864BC80E6",
|
|
88
|
+
details: {
|
|
89
|
+
chain: "bnb",
|
|
90
|
+
userAddress: "0x7265BDC334276e496d284D2Dcc2918aA59075a91",
|
|
91
|
+
inputAddress: "0xe7d40975DD0396Fc81A39b0ED1f2b7aCE1BC80E6",
|
|
92
|
+
historyScanned: 20,
|
|
93
|
+
poisonTxFound: true,
|
|
94
|
+
zeroValueFound: true,
|
|
95
|
+
dustFound: false,
|
|
96
|
+
},
|
|
97
|
+
error: null
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### `riskLevel` values
|
|
102
|
+
|
|
103
|
+
| Value | Meaning |
|
|
104
|
+
| ---------- | ----------------------------------------- |
|
|
105
|
+
| `none` | No signals detected — address looks clean |
|
|
106
|
+
| `low` | Weak signal — worth monitoring |
|
|
107
|
+
| `medium` | Suspicious — consider warning the user |
|
|
108
|
+
| `high` | Strong signal — warn the user |
|
|
109
|
+
| `critical` | Confirmed attack pattern — block the tx |
|
|
110
|
+
|
|
111
|
+
### `reason` values
|
|
112
|
+
|
|
113
|
+
| Value | Description |
|
|
114
|
+
| ------------------------ | ------------------------------------------------------------ |
|
|
115
|
+
| `address_poisoning` | Similar address found in user's transaction history |
|
|
116
|
+
| `zero_value_transfer` | Incoming ERC-20 transfer with value = 0 |
|
|
117
|
+
| `batch_poisoning` | Attacker contract poisoned history in a single batch tx |
|
|
118
|
+
| `transferfrom_spoofing` | Contract forced a zero-value transferFrom using your address |
|
|
119
|
+
| `dust_attack` | Micro-transaction received from unknown address |
|
|
120
|
+
| `new_suspicious_address` | Young address with outgoing-only activity |
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## API Reference
|
|
125
|
+
|
|
126
|
+
### `checkAddress(params)`
|
|
127
|
+
|
|
128
|
+
```ts
|
|
129
|
+
import { checkAddress } from "hexora"
|
|
130
|
+
|
|
131
|
+
const result = await checkAddress(params: CheckAddressParams): Promise<CheckResult>
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
#### `CheckAddressParams`
|
|
135
|
+
|
|
136
|
+
| Field | Type | Required | Default | Description |
|
|
137
|
+
| --------------------- | ----------------- | -------- | --------------------- | -------------------------------------- |
|
|
138
|
+
| `userAddress` | `string` | ✅ | — | The connected wallet address |
|
|
139
|
+
| `inputAddress` | `string` | ✅ | — | The address the user wants to send to |
|
|
140
|
+
| `provider` | `RawProvider` | ✅ | — | EIP-1193 or Phantom provider |
|
|
141
|
+
| `historyLimit` | `number` | ❌ | `20` | Transactions to scan (max 50) |
|
|
142
|
+
| `similarityThreshold` | `number` | ❌ | `85` | Minimum score to flag (0–100) |
|
|
143
|
+
| `dustThreshold` | `bigint` | ❌ | `10_000_000_000_000n` | Wei threshold for dust detection |
|
|
144
|
+
| `historyProvider` | `HistoryProvider` | ❌ | — | Custom transaction history source |
|
|
145
|
+
| `apiKeys.etherscan` | `string` | ❌ | — | Etherscan API key (higher rate limits) |
|
|
146
|
+
| `apiKeys.bscscan` | `string` | ❌ | — | BscScan API key |
|
|
147
|
+
| `apiKeys.polygonscan` | `string` | ❌ | — | Polygonscan API key |
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Supported Chains
|
|
152
|
+
|
|
153
|
+
| Chain | Status | Auto-detected from provider |
|
|
154
|
+
| --------- | ------ | --------------------------- |
|
|
155
|
+
| Ethereum | ✅ | `chainId: 0x1` |
|
|
156
|
+
| BNB Chain | ✅ | `chainId: 0x38` |
|
|
157
|
+
| Polygon | ✅ | `chainId: 0x89` |
|
|
158
|
+
| Avalanche | ✅ | `chainId: 0xa86a` |
|
|
159
|
+
| Arbitrum | ✅ | `chainId: 0xa4b1` |
|
|
160
|
+
| Optimism | ✅ | `chainId: 0xa` |
|
|
161
|
+
| Solana | 🔜 | Phantom provider |
|
|
162
|
+
| Bitcoin | 🔜 | Coming soon |
|
|
163
|
+
| Tron | 🔜 | Coming soon |
|
|
164
|
+
|
|
165
|
+
Chain is resolved **automatically** from the provider — you never pass `chain` manually.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Supported Wallets & Providers
|
|
170
|
+
|
|
171
|
+
HEXORA auto-detects the provider type. Any wallet that implements **EIP-1193** works out of the box:
|
|
172
|
+
|
|
173
|
+
| Wallet | Works |
|
|
174
|
+
| ------------------- | ----- |
|
|
175
|
+
| MetaMask | ✅ |
|
|
176
|
+
| WalletConnect | ✅ |
|
|
177
|
+
| Coinbase Wallet | ✅ |
|
|
178
|
+
| Trust Wallet (EVM) | ✅ |
|
|
179
|
+
| Rainbow | ✅ |
|
|
180
|
+
| Rabby | ✅ |
|
|
181
|
+
| Ledger Live | ✅ |
|
|
182
|
+
| Phantom (Solana) | ✅ |
|
|
183
|
+
| Any EIP-1193 wallet | ✅ |
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Usage Examples
|
|
188
|
+
|
|
189
|
+
### React
|
|
190
|
+
|
|
191
|
+
```tsx
|
|
192
|
+
import { checkAddress } from "hexora";
|
|
193
|
+
|
|
194
|
+
const handleSend = async () => {
|
|
195
|
+
const result = await checkAddress({
|
|
196
|
+
userAddress: account,
|
|
197
|
+
inputAddress: pastedAddress,
|
|
198
|
+
provider: window.ethereum,
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
if (result.scam) {
|
|
202
|
+
alert(`⚠️ ${result.reason} — risk: ${result.riskLevel}`);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// proceed with transaction
|
|
207
|
+
};
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Next.js
|
|
211
|
+
|
|
212
|
+
Works in client components only — `window.ethereum` is not available server-side.
|
|
213
|
+
|
|
214
|
+
```tsx
|
|
215
|
+
"use client";
|
|
216
|
+
import { checkAddress } from "hexora";
|
|
217
|
+
|
|
218
|
+
export function SendForm() {
|
|
219
|
+
const handleSubmit = async (e: React.FormEvent) => {
|
|
220
|
+
e.preventDefault();
|
|
221
|
+
const result = await checkAddress({
|
|
222
|
+
userAddress: userWallet,
|
|
223
|
+
inputAddress: recipientInput,
|
|
224
|
+
provider: window.ethereum,
|
|
225
|
+
});
|
|
226
|
+
if (result.scam) setWarning(result.reason);
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Vue 3
|
|
232
|
+
|
|
233
|
+
```ts
|
|
234
|
+
import { checkAddress } from "hexora";
|
|
235
|
+
|
|
236
|
+
async function onSend() {
|
|
237
|
+
const result = await checkAddress({
|
|
238
|
+
userAddress: wallet.address,
|
|
239
|
+
inputAddress: form.recipient,
|
|
240
|
+
provider: window.ethereum,
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
if (result.scam) {
|
|
244
|
+
warningMessage.value = result.reason;
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Svelte
|
|
251
|
+
|
|
252
|
+
```ts
|
|
253
|
+
import { checkAddress } from "hexora";
|
|
254
|
+
|
|
255
|
+
async function handleSend() {
|
|
256
|
+
const result = await checkAddress({
|
|
257
|
+
userAddress: $wallet.address,
|
|
258
|
+
inputAddress: recipientInput,
|
|
259
|
+
provider: window.ethereum,
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
if (result.scam) {
|
|
263
|
+
warning = result.reason;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### Angular
|
|
269
|
+
|
|
270
|
+
```ts
|
|
271
|
+
import { Injectable } from "@angular/core";
|
|
272
|
+
import { checkAddress } from "hexora";
|
|
273
|
+
|
|
274
|
+
@Injectable({ providedIn: "root" })
|
|
275
|
+
export class HexoraService {
|
|
276
|
+
async check(userAddress: string, inputAddress: string) {
|
|
277
|
+
return checkAddress({
|
|
278
|
+
userAddress,
|
|
279
|
+
inputAddress,
|
|
280
|
+
provider: (window as any).ethereum,
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### React Native
|
|
287
|
+
|
|
288
|
+
> Requires a WalletConnect or custom EIP-1193 compatible provider — `window.ethereum` is not available in React Native.
|
|
289
|
+
|
|
290
|
+
```tsx
|
|
291
|
+
import { checkAddress } from "hexora";
|
|
292
|
+
import { useWalletConnectModal } from "@walletconnect/modal-react-native";
|
|
293
|
+
|
|
294
|
+
export function SendScreen() {
|
|
295
|
+
const { provider } = useWalletConnectModal();
|
|
296
|
+
|
|
297
|
+
const handleSend = async () => {
|
|
298
|
+
const result = await checkAddress({
|
|
299
|
+
userAddress: connectedAddress,
|
|
300
|
+
inputAddress: recipientAddress,
|
|
301
|
+
provider: provider, // WalletConnect EIP-1193 provider
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
if (result.scam) {
|
|
305
|
+
Alert.alert("⚠️ Warning", `Suspicious address: ${result.reason}`);
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Node.js / Backend
|
|
313
|
+
|
|
314
|
+
Useful for pre-validating addresses in a backend before broadcasting transactions.
|
|
315
|
+
|
|
316
|
+
```ts
|
|
317
|
+
import { checkAddress } from "hexora";
|
|
318
|
+
import type { EIP1193Provider } from "hexora";
|
|
319
|
+
|
|
320
|
+
// Node.js has no window.ethereum — use your own RPC provider adapter
|
|
321
|
+
class NodeProvider implements EIP1193Provider {
|
|
322
|
+
async request({ method }: { method: string }): Promise<unknown> {
|
|
323
|
+
if (method === "eth_chainId") return "0x1";
|
|
324
|
+
throw new Error(`Unsupported method: ${method}`);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const result = await checkAddress({
|
|
329
|
+
userAddress: "0x7265BDC334276e496d284D2Dcc2918aA59075a91",
|
|
330
|
+
inputAddress: "0xe7d40975DD0396Fc81A39b0ED1f2b7aCE1BC80E6",
|
|
331
|
+
provider: new NodeProvider(),
|
|
332
|
+
apiKeys: { etherscan: process.env.ETHERSCAN_API_KEY },
|
|
333
|
+
});
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### Browser Extension (Chrome / Firefox)
|
|
337
|
+
|
|
338
|
+
```ts
|
|
339
|
+
import { checkAddress } from "hexora";
|
|
340
|
+
|
|
341
|
+
chrome.runtime.onMessage.addListener(async (msg, _sender, sendResponse) => {
|
|
342
|
+
if (msg.type === "CHECK_ADDRESS") {
|
|
343
|
+
const result = await checkAddress({
|
|
344
|
+
userAddress: msg.userAddress,
|
|
345
|
+
inputAddress: msg.inputAddress,
|
|
346
|
+
provider: window.ethereum,
|
|
347
|
+
});
|
|
348
|
+
sendResponse(result);
|
|
349
|
+
}
|
|
350
|
+
return true; // keep channel open for async response
|
|
351
|
+
});
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### With API Keys (higher rate limits)
|
|
355
|
+
|
|
356
|
+
```ts
|
|
357
|
+
const result = await checkAddress({
|
|
358
|
+
userAddress: account,
|
|
359
|
+
inputAddress: pastedAddress,
|
|
360
|
+
provider: window.ethereum,
|
|
361
|
+
apiKeys: {
|
|
362
|
+
etherscan: "YOUR_ETHERSCAN_KEY",
|
|
363
|
+
bscscan: "YOUR_BSCSCAN_KEY",
|
|
364
|
+
},
|
|
365
|
+
});
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### Custom History Provider
|
|
369
|
+
|
|
370
|
+
Implement `HistoryProvider` to plug in your own data source (Alchemy, Moralis, your own indexer):
|
|
371
|
+
|
|
372
|
+
```ts
|
|
373
|
+
import { checkAddress } from "hexora";
|
|
374
|
+
import type { HistoryProvider, NormalizedTransaction, ChainId } from "hexora";
|
|
375
|
+
|
|
376
|
+
class AlchemyProvider implements HistoryProvider {
|
|
377
|
+
async getTransactions(
|
|
378
|
+
address: string,
|
|
379
|
+
chain: ChainId,
|
|
380
|
+
limit: number
|
|
381
|
+
): Promise<NormalizedTransaction[]> {
|
|
382
|
+
// fetch from Alchemy / Moralis / your indexer
|
|
383
|
+
return [];
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
const result = await checkAddress({
|
|
388
|
+
userAddress: account,
|
|
389
|
+
inputAddress: pastedAddress,
|
|
390
|
+
provider: window.ethereum,
|
|
391
|
+
historyProvider: new AlchemyProvider(),
|
|
392
|
+
});
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
---
|
|
396
|
+
|
|
397
|
+
## Platform Support
|
|
398
|
+
|
|
399
|
+
| Platform | Status | Notes |
|
|
400
|
+
| ------------------ | ------ | ----------------------------------------- |
|
|
401
|
+
| React | ✅ | Full support |
|
|
402
|
+
| Next.js | ✅ | Client components only |
|
|
403
|
+
| Vue 3 | ✅ | Full support |
|
|
404
|
+
| Svelte / SvelteKit | ✅ | Full support |
|
|
405
|
+
| Angular | ✅ | Full support |
|
|
406
|
+
| React Native | ✅ | Requires WalletConnect or custom provider |
|
|
407
|
+
| Node.js | ✅ | Custom EIP-1193 adapter required |
|
|
408
|
+
| Browser Extension | ✅ | Chrome, Firefox, Edge |
|
|
409
|
+
| Vanilla JS | ✅ | Full support |
|
|
410
|
+
|
|
411
|
+
---
|
|
412
|
+
|
|
413
|
+
## Coming Soon
|
|
414
|
+
|
|
415
|
+
Native SDK support is planned for mobile platforms — no JS bridge required:
|
|
416
|
+
|
|
417
|
+
| Platform | Status | Notes |
|
|
418
|
+
| ---------------- | ------ | -------------------------------------- |
|
|
419
|
+
| Swift / iOS | 🔜 | Native Swift SDK |
|
|
420
|
+
| Kotlin / Android | 🔜 | Native Kotlin SDK |
|
|
421
|
+
| Flutter | 🔜 | Dart package |
|
|
422
|
+
| Rust | 🔜 | For CLI tools and backend integrations |
|
|
423
|
+
| Python | 🔜 | For backend / analytics use cases |
|
|
424
|
+
|
|
425
|
+
> Want to contribute a native SDK? Open an issue or reach out.
|
|
426
|
+
|
|
427
|
+
---
|
|
428
|
+
|
|
429
|
+
## Error Handling
|
|
430
|
+
|
|
431
|
+
HEXORA never throws. All errors are returned in `result.error`:
|
|
432
|
+
|
|
433
|
+
```ts
|
|
434
|
+
const result = await checkAddress({ ... })
|
|
435
|
+
|
|
436
|
+
if (result.error) {
|
|
437
|
+
console.error(result.error.code) // "network_unavailable"
|
|
438
|
+
console.error(result.error.message) // human-readable message
|
|
439
|
+
}
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
### Error codes
|
|
443
|
+
|
|
444
|
+
| Code | Description |
|
|
445
|
+
| ---------------------- | ----------------------------------- |
|
|
446
|
+
| `invalid_address` | Address format is invalid for chain |
|
|
447
|
+
| `unknown_provider` | Provider type could not be detected |
|
|
448
|
+
| `unsupported_chain` | Chain is not supported yet |
|
|
449
|
+
| `network_unavailable` | Could not connect to provider |
|
|
450
|
+
| `history_fetch_failed` | Transaction history fetch failed |
|
|
451
|
+
| `rate_limited` | API rate limit hit |
|
|
452
|
+
| `unknown` | Unexpected error |
|
|
453
|
+
|
|
454
|
+
---
|
|
455
|
+
|
|
456
|
+
## Packages
|
|
457
|
+
|
|
458
|
+
This is a monorepo. You can install the full SDK or individual packages:
|
|
459
|
+
|
|
460
|
+
| Package | Description | Size |
|
|
461
|
+
| ----------------------- | ---------------------------- | ----------- |
|
|
462
|
+
| `hexora` | Full SDK — all modules | ~3.5 kB |
|
|
463
|
+
| `@hexora/address-guard` | Address poisoning detection | ~3.5 kB |
|
|
464
|
+
| `@hexora/core` | Shared utilities and types | ~2.2 kB |
|
|
465
|
+
| `@hexora/domain-guard` | Domain phishing detection 🔜 | coming soon |
|
|
466
|
+
|
|
467
|
+
---
|
|
468
|
+
|
|
469
|
+
## Architecture
|
|
470
|
+
|
|
471
|
+
```
|
|
472
|
+
hexora/
|
|
473
|
+
├── packages/
|
|
474
|
+
│ ├── core/ — shared: types, provider detection, similarity, cache
|
|
475
|
+
│ ├── address-guard/ — address poisoning detection logic
|
|
476
|
+
│ ├── domain-guard/ — domain phishing detection (coming soon)
|
|
477
|
+
│ └── hexora/ — single entry point re-exporting all modules
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
Each package is independent. `@hexora/core` is shared — never duplicate logic across modules.
|
|
481
|
+
|
|
482
|
+
---
|
|
483
|
+
|
|
484
|
+
## Privacy
|
|
485
|
+
|
|
486
|
+
- All analysis runs **locally** — no data is sent to HEXORA servers
|
|
487
|
+
- Transaction history is fetched directly from public block explorer APIs
|
|
488
|
+
- In-memory cache only (5 min TTL) — cleared when the page unloads
|
|
489
|
+
- No `localStorage`, no cookies, no tracking
|
|
490
|
+
|
|
491
|
+
---
|
|
492
|
+
|
|
493
|
+
## License
|
|
494
|
+
|
|
495
|
+
MIT — free for personal and commercial use.
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hexora/address-guard",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"license": "MIT",
|
|
4
5
|
"type": "module",
|
|
5
6
|
"main": "./dist/index.js",
|
|
6
7
|
"module": "./dist/index.js",
|
|
@@ -15,7 +16,7 @@
|
|
|
15
16
|
"dist"
|
|
16
17
|
],
|
|
17
18
|
"dependencies": {
|
|
18
|
-
"@hexora/core": "1.0.
|
|
19
|
+
"@hexora/core": "1.0.1"
|
|
19
20
|
},
|
|
20
21
|
"devDependencies": {
|
|
21
22
|
"typescript": "^5.5.4",
|