@decentrys/protect 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 +153 -39
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
# @decentrys/protect
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Tells a user what a transaction actually does, before they sign it — without calling every new project a scam.**
|
|
4
|
+
|
|
5
|
+
You give it a pending transaction, a contract, a token or an address. It returns
|
|
6
|
+
observed facts, what the code *can* do, any threat signals with the evidence
|
|
7
|
+
behind them, and an explicit list of what it could not determine. Your app
|
|
8
|
+
decides what to do with that.
|
|
4
9
|
|
|
5
10
|
> **Lack of evidence is not evidence of malice.**
|
|
6
11
|
>
|
|
7
12
|
> A contract deployed two hours ago by an anonymous wallet with no audit and
|
|
8
|
-
> thin liquidity is *unknown*, not dangerous.
|
|
9
|
-
>
|
|
10
|
-
>
|
|
11
|
-
> to do that, and there is no code path by which newness can raise a risk
|
|
13
|
+
> thin liquidity is *unknown*, not dangerous. Most tooling scores those facts as
|
|
14
|
+
> risk, which taxes every new project and protects incumbents. There is no code
|
|
15
|
+
> path in this package by which newness, anonymity or obscurity can raise a risk
|
|
12
16
|
> level.
|
|
13
17
|
|
|
14
18
|
## Install
|
|
@@ -17,66 +21,176 @@ Evidence-based on-chain risk assessment for wallets and dapps.
|
|
|
17
21
|
npm install @decentrys/protect
|
|
18
22
|
```
|
|
19
23
|
|
|
20
|
-
|
|
24
|
+
Zero dependencies. Works in Node 18+, browsers, extensions and React Native.
|
|
25
|
+
|
|
26
|
+
## Getting an API key
|
|
27
|
+
|
|
28
|
+
Sign in at [decentrys.com/developers](https://decentrys.com/developers) and create a key.
|
|
29
|
+
|
|
30
|
+
There are two kinds, and picking the wrong one is the mistake that matters:
|
|
31
|
+
|
|
32
|
+
| Prefix | Where it belongs | Why |
|
|
33
|
+
|---|---|---|
|
|
34
|
+
| `dk_pub_live_…` | **Publishable.** Ships inside a wallet, extension or mobile app. | Bounded to the origins you register and to read-only Protect endpoints. Anyone can extract it from your bundle; that's expected, and it's why it can't do anything dangerous. |
|
|
35
|
+
| `dk_live_…` | **Secret.** Server-side only. | Full scope access. If this ends up in a client bundle it is a leaked credential the moment it ships. |
|
|
36
|
+
|
|
37
|
+
## Quick start
|
|
21
38
|
|
|
22
39
|
```ts
|
|
23
40
|
import { Decentrys } from '@decentrys/protect';
|
|
24
41
|
|
|
25
|
-
const decentrys = new Decentrys({
|
|
42
|
+
const decentrys = new Decentrys({
|
|
43
|
+
apiKey: 'dk_pub_live_...',
|
|
44
|
+
failMode: 'warn', // what to do if Decentrys is unreachable
|
|
45
|
+
timeoutMs: 4000, // a deadline, not a target
|
|
46
|
+
});
|
|
26
47
|
|
|
27
|
-
const
|
|
48
|
+
const result = await decentrys.assessTransaction({
|
|
28
49
|
chain: 'ethereum',
|
|
29
50
|
from: userAddress,
|
|
30
51
|
to: contractAddress,
|
|
31
52
|
data: calldata,
|
|
32
53
|
});
|
|
54
|
+
```
|
|
33
55
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
56
|
+
## What you get back
|
|
57
|
+
|
|
58
|
+
```jsonc
|
|
59
|
+
{
|
|
60
|
+
"assessment": {
|
|
61
|
+
"riskLevel": "CAUTION",
|
|
62
|
+
"confirmedMalicious": false,
|
|
63
|
+
"confidence": 0.7,
|
|
64
|
+
"historyStatus": "LIMITED",
|
|
65
|
+
|
|
66
|
+
// Directly verifiable. Carry no accusation.
|
|
67
|
+
"facts": [
|
|
68
|
+
{ "type": "DEPLOYED_AT", "statement": "The contract was deployed on 2026-09-04." }
|
|
69
|
+
],
|
|
70
|
+
|
|
71
|
+
// What the code CAN do. A capability is not a vulnerability.
|
|
72
|
+
"capabilities": [
|
|
73
|
+
{ "type": "UPGRADEABLE", "severity": "SIGNIFICANT",
|
|
74
|
+
"statement": "The contract is a proxy: whoever holds its upgrade rights can replace its logic after you approve it." }
|
|
75
|
+
],
|
|
76
|
+
|
|
77
|
+
// The only thing that can raise a risk level. Each carries its evidence.
|
|
78
|
+
"threatSignals": [],
|
|
79
|
+
|
|
80
|
+
// Stated, never silently omitted.
|
|
81
|
+
"unknowns": [
|
|
82
|
+
{ "field": "simulation", "reason": "INSUFFICIENT_DATA",
|
|
83
|
+
"statement": "The transaction was not simulated, so its effect on balances is not known here." }
|
|
84
|
+
],
|
|
85
|
+
|
|
86
|
+
"explanation": ["The contract is a proxy: ...", "Little history is available yet. This is normal ..."]
|
|
87
|
+
},
|
|
88
|
+
"decision": { "action": "warn", "reason": "..." }
|
|
89
|
+
}
|
|
39
90
|
```
|
|
40
91
|
|
|
41
|
-
##
|
|
92
|
+
## Wiring it into a wallet
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
// 1. Before showing the signing screen
|
|
96
|
+
const { assessment, decision } = await decentrys.assessTransaction(tx);
|
|
97
|
+
|
|
98
|
+
// 2. Show what it does, in words
|
|
99
|
+
const explained = await decentrys.explainTransaction(tx);
|
|
100
|
+
// explained.summary -> "Grant 0x1111… unlimited permission to spend the token at 0xabc… from your wallet."
|
|
101
|
+
// explained.exposure -> ["0x1111… will be able to move this token out of your wallet at any time, ..."]
|
|
102
|
+
|
|
103
|
+
// 3. Act on YOUR policy, not ours
|
|
104
|
+
switch (decision.action) {
|
|
105
|
+
case 'allow': return sign();
|
|
106
|
+
case 'inform': return showDetails(assessment);
|
|
107
|
+
case 'warn':
|
|
108
|
+
case 'warn_strong': return showWarning(assessment);
|
|
109
|
+
case 'require_confirmation': return showWarning(assessment, { requireTypedConfirm: true });
|
|
110
|
+
case 'block': return refuse(assessment);
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Render it with [`@decentrys/ui-sdk`](https://www.npmjs.com/package/@decentrys/ui-sdk) if you don't want to build the UI yourself.
|
|
115
|
+
|
|
116
|
+
## Every method
|
|
117
|
+
|
|
118
|
+
| Method | Answers |
|
|
119
|
+
|---|---|
|
|
120
|
+
| `assessTransaction(tx)` | Is this transaction worth warning about? |
|
|
121
|
+
| `explainTransaction(tx)` | What does it actually do, in plain language? |
|
|
122
|
+
| `simulateTransaction(tx)` | What would change if I signed it? |
|
|
123
|
+
| `scanContract({chain,address})` | What can this contract do — upgrade, mint, pause, freeze? |
|
|
124
|
+
| `screenToken({chain,address})` | What is this token, and what powers does it hold? |
|
|
125
|
+
| `screenAddress({chain,address})` | What is known about this address? |
|
|
126
|
+
| `screenApproval({chain,owner,spender,token,amount})` | What am I granting, and to whom? |
|
|
127
|
+
| `assessDapp({origin})` | Is this site reported phishing infrastructure? |
|
|
128
|
+
| `getThreatSignals({chain,address})` | Signals only, for your own presentation. |
|
|
42
129
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
130
|
+
## Two guarantees
|
|
131
|
+
|
|
132
|
+
**It never throws.** This runs between a user and a signing screen. If Decentrys
|
|
133
|
+
is unreachable you get an assessment saying exactly that in `unknowns`, with
|
|
134
|
+
`confidence: 0` — never a reassuring result it didn't earn, and never an
|
|
135
|
+
exception your wallet has to catch.
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
const { assessment } = await decentrys.screenAddress({ chain: 'ethereum', address });
|
|
139
|
+
if (assessment.unknowns.some(u => u.reason === 'PROVIDER_UNAVAILABLE')) {
|
|
140
|
+
// Nothing was checked. Say so; don't show a green tick.
|
|
141
|
+
}
|
|
142
|
+
```
|
|
47
143
|
|
|
48
144
|
**It never blocks.** Decentrys returns intelligence; your policy decides. The
|
|
49
|
-
default blocks only `KNOWN_MALICIOUS`, which requires analyst-verified
|
|
50
|
-
|
|
145
|
+
default blocks only `KNOWN_MALICIOUS`, which requires analyst-verified evidence
|
|
146
|
+
because it's the one output that accuses a third party.
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
new Decentrys({ apiKey, policy: { HIGH_RISK: 'block', CAUTION: 'inform' } });
|
|
150
|
+
```
|
|
51
151
|
|
|
52
152
|
## Risk levels
|
|
53
153
|
|
|
54
|
-
|
|
55
|
-
`
|
|
56
|
-
`KNOWN_MALICIOUS`. Capabilities can reach `CAUTION`; only threat signals with
|
|
57
|
-
evidence go past it.
|
|
154
|
+
`NO_CRITICAL_RISK_DETECTED` · `INFORMATIONAL` · `CAUTION` · `ELEVATED_RISK` ·
|
|
155
|
+
`HIGH_RISK` · `CRITICAL_THREAT` · `KNOWN_MALICIOUS`
|
|
58
156
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
must not be rendered as a warning.
|
|
157
|
+
Capabilities can reach `CAUTION`. Only threat signals with evidence go past it.
|
|
158
|
+
`RISK_LEVEL_MEANING[level]` gives wording safe to show a user.
|
|
62
159
|
|
|
63
|
-
|
|
160
|
+
**`historyStatus: 'LIMITED'` is not a warning.** It measures how much *Decentrys*
|
|
161
|
+
knows, never the subject's danger, and is the correct state for anything
|
|
162
|
+
recently deployed. Render it neutrally.
|
|
64
163
|
|
|
65
|
-
|
|
66
|
-
pages with a strict CSP: `@decentrys/protect/browser`, global
|
|
67
|
-
`DecentrysProtect`.
|
|
164
|
+
## Browsers and extensions
|
|
68
165
|
|
|
69
|
-
|
|
166
|
+
```html
|
|
167
|
+
<script src="node_modules/@decentrys/protect/dist/browser/decentrys-protect.js"></script>
|
|
168
|
+
<script>const d = new DecentrysProtect.Decentrys({ apiKey: 'dk_pub_live_...' });</script>
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
ESM at `@decentrys/protect/browser`. Both bundles are dependency-free, for
|
|
172
|
+
pages with a strict CSP.
|
|
173
|
+
|
|
174
|
+
## Read the tests
|
|
70
175
|
|
|
71
|
-
`src/classify.test.ts` encodes the cases that must
|
|
72
|
-
that a brand-new unaudited contract
|
|
73
|
-
`INFORMATIONAL`, not a threat.
|
|
176
|
+
`src/classify.test.ts` ships with the package and encodes the cases that must
|
|
177
|
+
never regress — including that a brand-new unaudited contract from an anonymous
|
|
178
|
+
deployer is `INFORMATIONAL`, not a threat. You don't have to take the claim on
|
|
179
|
+
trust.
|
|
180
|
+
|
|
181
|
+
## The rest of the SDK
|
|
182
|
+
|
|
183
|
+
| Package | For |
|
|
184
|
+
|---|---|
|
|
185
|
+
| [`@decentrys/protect`](https://www.npmjs.com/package/@decentrys/protect) | Pre-sign risk assessment for wallets and dapps |
|
|
186
|
+
| [`@decentrys/ui-sdk`](https://www.npmjs.com/package/@decentrys/ui-sdk) | React components that render Protect results |
|
|
187
|
+
| [`@decentrys/sentinel-sdk`](https://www.npmjs.com/package/@decentrys/sentinel-sdk) | Monitoring deployed contracts and treasuries |
|
|
188
|
+
| [`@decentrys/risk-sdk`](https://www.npmjs.com/package/@decentrys/risk-sdk) | Screening for exchanges and custodians |
|
|
189
|
+
| [`@decentrys/dri-sdk`](https://www.npmjs.com/package/@decentrys/dri-sdk) | Fund tracing and recovery intelligence |
|
|
190
|
+
| [`@decentrys/agent`](https://www.npmjs.com/package/@decentrys/agent) | Policy enforcement for autonomous agents |
|
|
74
191
|
|
|
75
192
|
## Licence
|
|
76
193
|
|
|
77
194
|
MIT © Decentrys Labs
|
|
78
195
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
- [decentrys.com](https://decentrys.com) · [SDK overview](https://decentrys.com/sdk) · [Developer API](https://decentrys.com/developers)
|
|
82
|
-
- Source: [github.com/teamdecentrys-byte/Decentrys](https://github.com/teamdecentrys-byte/Decentrys)
|
|
196
|
+
[decentrys.com](https://decentrys.com) · [SDK overview](https://decentrys.com/sdk) · [Developer API](https://decentrys.com/developers) · [Source](https://github.com/teamdecentrys-byte/Decentrys)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decentrys/protect",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Evidence-based on-chain risk assessment for wallets and dapps. Unknown is neutral, risk requires evidence, and nothing is ever called a scam without one.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Decentrys Labs",
|