@saviours/check 0.1.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 ADDED
@@ -0,0 +1,53 @@
1
+ # `@saviours/check`
2
+
3
+ Two-line counterparty check. Default path talks to Sepolia ENS only — **zero** `@saviours/core`, **$0**, no our server.
4
+
5
+ ```ts
6
+ import { check } from "@saviours/check";
7
+
8
+ const r = await check("0x935bfb495e33f74d2e9735df1da66ace442ede48");
9
+ if (r.decision === "BLOCK") throw new Error("counterparty is named TAINTED");
10
+ ```
11
+
12
+ | Mode | Path | Cost | Our server? |
13
+ |---|---|---|---|
14
+ | `ens` (default) | PermissionedResolver.text | $0 | No |
15
+ | `shield` | `POST /api/shield/check` | $0 | Gateway |
16
+ | `full` | `POST /api/investigate` | ~USDC on miss | Gateway |
17
+
18
+ Also: `guard(address)`, `castCommand(address)`.
19
+
20
+ ## Install
21
+
22
+ ### From git (works today)
23
+
24
+ ```bash
25
+ pnpm add github:devhb1/Saviour#path:packages/check
26
+ # or
27
+ npm install github:devhb1/Saviour#path:packages/check
28
+ ```
29
+
30
+ `prepare` runs `tsc` on install so `dist/` is built (it is gitignored in the monorepo).
31
+
32
+ ### From npm (after publish)
33
+
34
+ ```bash
35
+ pnpm add @saviours/check
36
+ ```
37
+
38
+ Requires the npm org `@saviours` and:
39
+
40
+ ```bash
41
+ cd packages/check
42
+ npm login
43
+ npm publish --access public
44
+ ```
45
+
46
+ ## Smoke
47
+
48
+ ```bash
49
+ node --input-type=module -e "
50
+ import { check } from '@saviours/check';
51
+ console.log(await check('0x935bfb495e33f74d2e9735df1da66ace442ede48'));
52
+ "
53
+ ```
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Verifiable one-liner — same path as Identity / live-agent (no our server).
3
+ */
4
+ export declare function castCommand(address: string, opts?: {
5
+ resolver?: string;
6
+ parent?: string;
7
+ key?: string;
8
+ }): string;
9
+ //# sourceMappingURL=castCommand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"castCommand.d.ts","sourceRoot":"","sources":["../src/castCommand.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAC1D,MAAM,CAUR"}
@@ -0,0 +1,16 @@
1
+ const DEFAULT_RESOLVER = "0xF479306621F718F7d76875f67506ceD33717751c";
2
+ /**
3
+ * Verifiable one-liner — same path as Identity / live-agent (no our server).
4
+ */
5
+ export function castCommand(address, opts) {
6
+ const a = address.trim().toLowerCase();
7
+ if (!/^0x[a-f0-9]{40}$/.test(a)) {
8
+ throw new Error(`Invalid address: ${address}`);
9
+ }
10
+ const parent = opts?.parent ?? "saviours.eth";
11
+ const resolver = opts?.resolver ?? DEFAULT_RESOLVER;
12
+ const key = opts?.key ?? "saviours.status";
13
+ const ens = `${a}.${parent}`;
14
+ return `cast call ${resolver} "text(bytes32,string)(string)" $(cast namehash ${ens}) "${key}"`;
15
+ }
16
+ //# sourceMappingURL=castCommand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"castCommand.js","sourceRoot":"","sources":["../src/castCommand.ts"],"names":[],"mappings":"AAAA,MAAM,gBAAgB,GACpB,4CAAqD,CAAC;AAExD;;GAEG;AACH,MAAM,UAAU,WAAW,CACzB,OAAe,EACf,IAA2D;IAE3D,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACvC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAC;IACjD,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,EAAE,MAAM,IAAI,cAAc,CAAC;IAC9C,MAAM,QAAQ,GAAG,IAAI,EAAE,QAAQ,IAAI,gBAAgB,CAAC;IACpD,MAAM,GAAG,GAAG,IAAI,EAAE,GAAG,IAAI,iBAAiB,CAAC;IAC3C,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,MAAM,EAAE,CAAC;IAC7B,OAAO,aAAa,QAAQ,mDAAmD,GAAG,MAAM,GAAG,GAAG,CAAC;AACjG,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { CheckOptions, CheckResult } from "./types.js";
2
+ /**
3
+ * Counterparty check.
4
+ *
5
+ * - `ens` (default): Sepolia PermissionedResolver · $0 · no our server
6
+ * - `shield`: POST /api/shield/check · $0 · gateway
7
+ * - `full`: POST /api/investigate · ~$0.01 on miss · gateway
8
+ */
9
+ export declare function check(address: string, opts?: CheckOptions): Promise<CheckResult>;
10
+ //# sourceMappingURL=check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE5D;;;;;;GAMG;AACH,wBAAsB,KAAK,CACzB,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,YAAiB,GACtB,OAAO,CAAC,WAAW,CAAC,CAKtB"}
package/dist/check.js ADDED
@@ -0,0 +1,18 @@
1
+ import { checkEns } from "./ens.js";
2
+ import { checkFull, checkShield } from "./gateway.js";
3
+ /**
4
+ * Counterparty check.
5
+ *
6
+ * - `ens` (default): Sepolia PermissionedResolver · $0 · no our server
7
+ * - `shield`: POST /api/shield/check · $0 · gateway
8
+ * - `full`: POST /api/investigate · ~$0.01 on miss · gateway
9
+ */
10
+ export async function check(address, opts = {}) {
11
+ const mode = opts.mode ?? "ens";
12
+ if (mode === "shield")
13
+ return checkShield(address, opts);
14
+ if (mode === "full")
15
+ return checkFull(address, opts);
16
+ return checkEns(address, opts);
17
+ }
18
+ //# sourceMappingURL=check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.js","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGtD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CACzB,OAAe,EACf,OAAqB,EAAE;IAEvB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC;IAChC,IAAI,IAAI,KAAK,QAAQ;QAAE,OAAO,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACzD,IAAI,IAAI,KAAK,MAAM;QAAE,OAAO,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACrD,OAAO,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AACjC,CAAC"}
package/dist/ens.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * ENS-only check — imports nothing from @saviours/core.
3
+ * Mirror of consumers/live-agent/src/ensShield.ts.
4
+ */
5
+ import type { CheckOptions, CheckResult } from "./types.js";
6
+ export declare function checkEns(address: string, opts?: CheckOptions): Promise<CheckResult>;
7
+ //# sourceMappingURL=ens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ens.d.ts","sourceRoot":"","sources":["../src/ens.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAY,MAAM,YAAY,CAAC;AAkCtE,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,YAAiB,GACtB,OAAO,CAAC,WAAW,CAAC,CAyDtB"}
package/dist/ens.js ADDED
@@ -0,0 +1,89 @@
1
+ /**
2
+ * ENS-only check — imports nothing from @saviours/core.
3
+ * Mirror of consumers/live-agent/src/ensShield.ts.
4
+ */
5
+ import { createPublicClient, http } from "viem";
6
+ import { namehash } from "viem/ens";
7
+ import { sepolia } from "viem/chains";
8
+ const DEFAULT_RESOLVER = "0xF479306621F718F7d76875f67506ceD33717751c";
9
+ const textAbi = [
10
+ {
11
+ name: "text",
12
+ type: "function",
13
+ stateMutability: "view",
14
+ inputs: [
15
+ { name: "node", type: "bytes32" },
16
+ { name: "key", type: "string" },
17
+ ],
18
+ outputs: [{ name: "", type: "string" }],
19
+ },
20
+ ];
21
+ function requireAddress(address) {
22
+ const a = address.trim().toLowerCase();
23
+ if (!/^0x[a-f0-9]{40}$/.test(a)) {
24
+ throw new Error(`Invalid address: ${address}`);
25
+ }
26
+ return a;
27
+ }
28
+ function decisionFromStatus(status) {
29
+ const s = status.toUpperCase();
30
+ if (s === "TAINTED")
31
+ return "BLOCK";
32
+ if (s === "WATCH")
33
+ return "WARN";
34
+ if (s === "SAFE")
35
+ return "ALLOW";
36
+ return "ESCALATE";
37
+ }
38
+ export async function checkEns(address, opts = {}) {
39
+ const addr = requireAddress(address);
40
+ const parent = opts.parent ?? "saviours.eth";
41
+ const resolver = (opts.resolver ?? DEFAULT_RESOLVER);
42
+ const rpcUrl = opts.rpcUrl ??
43
+ process.env.SEPOLIA_RPC_URL ??
44
+ "https://ethereum-sepolia-rpc.publicnode.com";
45
+ const ensName = `${addr}.${parent}`;
46
+ const t0 = Date.now();
47
+ const client = createPublicClient({
48
+ chain: sepolia,
49
+ transport: http(rpcUrl),
50
+ });
51
+ const node = namehash(ensName);
52
+ const readText = (key) => client.readContract({
53
+ address: resolver,
54
+ abi: textAbi,
55
+ functionName: "text",
56
+ args: [node, key],
57
+ });
58
+ const status = (await readText("saviours.status")).trim();
59
+ if (!status) {
60
+ return {
61
+ decision: "ESCALATE",
62
+ status: "UNKNOWN",
63
+ ensName,
64
+ source: "none",
65
+ reason: "No saviours.status on ENS",
66
+ latencyMs: Date.now() - t0,
67
+ cost: { graph: 0, ai: 0, usd: 0 },
68
+ mode: "ens",
69
+ };
70
+ }
71
+ const [threat, evidenceHash, atomicTx] = await Promise.all([
72
+ readText("saviours.threat"),
73
+ readText("saviours.evidenceHash"),
74
+ readText("saviours.atomicTx"),
75
+ ]);
76
+ return {
77
+ decision: decisionFromStatus(status),
78
+ status,
79
+ ensName,
80
+ source: "ens",
81
+ threat: threat || undefined,
82
+ evidenceHash: evidenceHash || undefined,
83
+ atomicTx: atomicTx || undefined,
84
+ latencyMs: Date.now() - t0,
85
+ cost: { graph: 0, ai: 0, usd: 0 },
86
+ mode: "ens",
87
+ };
88
+ }
89
+ //# sourceMappingURL=ens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ens.js","sourceRoot":"","sources":["../src/ens.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { CheckOptions, CheckResult } from "./types.js";
2
+ export declare function checkShield(address: string, opts?: CheckOptions): Promise<CheckResult>;
3
+ export declare function checkFull(address: string, opts?: CheckOptions): Promise<CheckResult>;
4
+ //# sourceMappingURL=gateway.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../src/gateway.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAY,MAAM,YAAY,CAAC;AAqBtE,wBAAsB,WAAW,CAC/B,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,YAAiB,GACtB,OAAO,CAAC,WAAW,CAAC,CA4DtB;AAED,wBAAsB,SAAS,CAC7B,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,YAAiB,GACtB,OAAO,CAAC,WAAW,CAAC,CA0DtB"}
@@ -0,0 +1,110 @@
1
+ const DEFAULT_BASE = "https://www.saviours.xyz";
2
+ function requireAddress(address) {
3
+ const a = address.trim().toLowerCase();
4
+ if (!/^0x[a-f0-9]{40}$/.test(a)) {
5
+ throw new Error(`Invalid address: ${address}`);
6
+ }
7
+ return a;
8
+ }
9
+ function baseUrl(opts) {
10
+ return (opts.baseUrl ??
11
+ process.env.SAVIOURS_BASE_URL ??
12
+ process.env.PUBLIC_APP_URL ??
13
+ DEFAULT_BASE).replace(/\/$/, "");
14
+ }
15
+ export async function checkShield(address, opts = {}) {
16
+ const addr = requireAddress(address);
17
+ const t0 = Date.now();
18
+ const res = await fetch(`${baseUrl(opts)}/api/shield/check`, {
19
+ method: "POST",
20
+ headers: { "content-type": "application/json" },
21
+ body: JSON.stringify({
22
+ chainId: opts.chainId ?? 1,
23
+ address: addr,
24
+ registryNetwork: opts.registryNetwork ?? "sepolia",
25
+ }),
26
+ });
27
+ const json = (await res.json());
28
+ if (!res.ok || !json.check?.decision) {
29
+ throw new Error(json.error || `shield/check HTTP ${res.status}`);
30
+ }
31
+ const sourceRaw = (json.check.source ?? "none").toLowerCase();
32
+ const source = sourceRaw === "ens" || sourceRaw === "registry"
33
+ ? sourceRaw === "ens"
34
+ ? "ens"
35
+ : "shield"
36
+ : "none";
37
+ return {
38
+ decision: json.check.decision,
39
+ status: json.check.decision === "BLOCK"
40
+ ? "TAINTED"
41
+ : json.check.decision === "WARN"
42
+ ? "WATCH"
43
+ : json.check.decision === "ALLOW"
44
+ ? "SAFE"
45
+ : "UNKNOWN",
46
+ ensName: json.check.ensName ??
47
+ `${addr}.saviours.eth`,
48
+ source: source === "none" && json.check.decision === "ESCALATE" ? "none" : source === "ens" ? "ens" : "shield",
49
+ reason: json.check.reason,
50
+ latencyMs: typeof json.check.latencyMs === "number"
51
+ ? json.check.latencyMs
52
+ : Date.now() - t0,
53
+ cost: {
54
+ graph: json.memoryHit?.graphQueries ?? 0,
55
+ ai: json.memoryHit?.aiCalls ?? 0,
56
+ usd: 0,
57
+ },
58
+ mode: "shield",
59
+ };
60
+ }
61
+ export async function checkFull(address, opts = {}) {
62
+ const addr = requireAddress(address);
63
+ const t0 = Date.now();
64
+ const res = await fetch(`${baseUrl(opts)}/api/investigate`, {
65
+ method: "POST",
66
+ headers: { "content-type": "application/json" },
67
+ body: JSON.stringify({
68
+ chainId: opts.chainId ?? 1,
69
+ address: addr,
70
+ persist: opts.persist ?? false,
71
+ forceFresh: opts.forceFresh ?? false,
72
+ registryNetwork: opts.registryNetwork ?? "sepolia",
73
+ }),
74
+ });
75
+ const json = (await res.json());
76
+ if (!res.ok) {
77
+ throw new Error(json.error || `investigate HTTP ${res.status}`);
78
+ }
79
+ const status = (json.assessment?.status ?? "UNKNOWN").toUpperCase();
80
+ let decision = "ESCALATE";
81
+ if (status === "TAINTED")
82
+ decision = "BLOCK";
83
+ else if (status === "WATCH")
84
+ decision = "WARN";
85
+ else if (status === "SAFE")
86
+ decision = "ALLOW";
87
+ else if (json.shield?.decision)
88
+ decision = json.shield.decision;
89
+ const graph = json.cost?.graphQueries ?? 0;
90
+ const ai = json.cost?.aiCalls ?? 0;
91
+ const hit = Boolean(json.memoryHit ?? json.cost?.memoryHit);
92
+ return {
93
+ decision,
94
+ status,
95
+ ensName: `${addr}.saviours.eth`,
96
+ source: hit ? "shield" : "investigate",
97
+ threat: json.assessment?.threatTypes?.join(" ∧ "),
98
+ latencyMs: json.cost?.latencyMs ?? Date.now() - t0,
99
+ cost: {
100
+ graph,
101
+ ai,
102
+ usd: hit ? 0 : 0.01,
103
+ },
104
+ mode: "full",
105
+ reason: hit
106
+ ? "MEMORY HIT short-circuit"
107
+ : "Fresh investigation (Graph + AI cite + validator)",
108
+ };
109
+ }
110
+ //# sourceMappingURL=gateway.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gateway.js","sourceRoot":"","sources":["../src/gateway.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { CheckOptions, CheckResult } from "./types.js";
2
+ export declare class SavioursBlockedError extends Error {
3
+ readonly result: CheckResult;
4
+ constructor(result: CheckResult);
5
+ }
6
+ /**
7
+ * Drop-in for signer middleware: throws on BLOCK, returns result on WARN/ALLOW/ESCALATE.
8
+ * WARN is returned (not thrown) so callers can reduce size — never silent.
9
+ */
10
+ export declare function guard(address: string, opts?: CheckOptions): Promise<CheckResult>;
11
+ //# sourceMappingURL=guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../src/guard.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE5D,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;gBACjB,MAAM,EAAE,WAAW;CAQhC;AAED;;;GAGG;AACH,wBAAsB,KAAK,CACzB,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,YAAiB,GACtB,OAAO,CAAC,WAAW,CAAC,CAMtB"}
package/dist/guard.js ADDED
@@ -0,0 +1,22 @@
1
+ import { check } from "./check.js";
2
+ export class SavioursBlockedError extends Error {
3
+ result;
4
+ constructor(result) {
5
+ super(`SAVIOURS BLOCK: ${result.ensName} status=${result.status}` +
6
+ (result.threat ? ` threat=${result.threat}` : ""));
7
+ this.name = "SavioursBlockedError";
8
+ this.result = result;
9
+ }
10
+ }
11
+ /**
12
+ * Drop-in for signer middleware: throws on BLOCK, returns result on WARN/ALLOW/ESCALATE.
13
+ * WARN is returned (not thrown) so callers can reduce size — never silent.
14
+ */
15
+ export async function guard(address, opts = {}) {
16
+ const result = await check(address, opts);
17
+ if (result.decision === "BLOCK") {
18
+ throw new SavioursBlockedError(result);
19
+ }
20
+ return result;
21
+ }
22
+ //# sourceMappingURL=guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guard.js","sourceRoot":"","sources":["../src/guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGnC,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IACpC,MAAM,CAAc;IAC7B,YAAY,MAAmB;QAC7B,KAAK,CACH,mBAAmB,MAAM,CAAC,OAAO,WAAW,MAAM,CAAC,MAAM,EAAE;YACzD,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CACpD,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;QACnC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CACzB,OAAe,EACf,OAAqB,EAAE;IAEvB,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC1C,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAChC,MAAM,IAAI,oBAAoB,CAAC,MAAM,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,7 @@
1
+ export { check } from "./check.js";
2
+ export { guard, SavioursBlockedError } from "./guard.js";
3
+ export { castCommand } from "./castCommand.js";
4
+ export { checkEns } from "./ens.js";
5
+ export { checkShield, checkFull } from "./gateway.js";
6
+ export type { CheckCost, CheckMode, CheckOptions, CheckResult, Decision, } from "./types.js";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACtD,YAAY,EACV,SAAS,EACT,SAAS,EACT,YAAY,EACZ,WAAW,EACX,QAAQ,GACT,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { check } from "./check.js";
2
+ export { guard, SavioursBlockedError } from "./guard.js";
3
+ export { castCommand } from "./castCommand.js";
4
+ export { checkEns } from "./ens.js";
5
+ export { checkShield, checkFull } from "./gateway.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Optional React entry — peer-free types; apps re-export a fetch-based hook.
3
+ * Node agents should use `check()` / `guard()` from the main entry (viem ENS).
4
+ */
5
+ export { check, guard, castCommand } from "./index.js";
6
+ export type { CheckResult, CheckOptions, Decision } from "./types.js";
7
+ //# sourceMappingURL=react.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACvD,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}
package/dist/react.js ADDED
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Optional React entry — peer-free types; apps re-export a fetch-based hook.
3
+ * Node agents should use `check()` / `guard()` from the main entry (viem ENS).
4
+ */
5
+ export { check, guard, castCommand } from "./index.js";
6
+ //# sourceMappingURL=react.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.js","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,39 @@
1
+ export type Decision = "BLOCK" | "WARN" | "ALLOW" | "ESCALATE";
2
+ export type CheckMode = "ens" | "shield" | "full";
3
+ export type CheckCost = {
4
+ graph: number;
5
+ ai: number;
6
+ usd: number;
7
+ };
8
+ export type CheckResult = {
9
+ decision: Decision;
10
+ status: string;
11
+ ensName: string;
12
+ source: "ens" | "shield" | "investigate" | "none";
13
+ threat?: string;
14
+ evidenceHash?: string;
15
+ atomicTx?: string;
16
+ reason?: string;
17
+ latencyMs: number;
18
+ cost: CheckCost;
19
+ mode: CheckMode;
20
+ };
21
+ export type CheckOptions = {
22
+ /** ens (default) | shield | full */
23
+ mode?: CheckMode;
24
+ /** Sepolia RPC for mode=ens. Defaults to publicnode. */
25
+ rpcUrl?: string;
26
+ /** PermissionedResolver proxy. */
27
+ resolver?: `0x${string}`;
28
+ /** Parent name, default saviours.eth */
29
+ parent?: string;
30
+ /** Gateway / app origin for shield + full. */
31
+ baseUrl?: string;
32
+ chainId?: number;
33
+ registryNetwork?: "sepolia" | "anvil";
34
+ /** full mode only — force Graph path */
35
+ forceFresh?: boolean;
36
+ /** full mode only — attempt Remember (usually false on public) */
37
+ persist?: boolean;
38
+ };
39
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,CAAC;AAE/D,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;AAElD,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,KAAK,GAAG,QAAQ,GAAG,aAAa,GAAG,MAAM,CAAC;IAClD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,SAAS,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,oCAAoC;IACpC,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,QAAQ,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;IACzB,wCAAwC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;IACtC,wCAAwC;IACxC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,kEAAkE;IAClE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,15 @@
1
+ import { check, castCommand, guard } from "@saviours/check";
2
+
3
+ const ATTACK_1 = "0x935bfb495e33f74d2e9735df1da66ace442ede48";
4
+
5
+ const r = await check(ATTACK_1);
6
+ console.log(r);
7
+ // { decision: "BLOCK", status: "TAINTED", source: "ens", cost: { graph: 0, ai: 0, usd: 0 }, … }
8
+
9
+ console.log(castCommand(ATTACK_1));
10
+
11
+ try {
12
+ await guard(ATTACK_1);
13
+ } catch (e) {
14
+ console.error(String(e));
15
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Example — wrap a viem wallet client sendTransaction with guard().
3
+ * Not shipped as a dependency; copy into your agent.
4
+ */
5
+ import { guard, SavioursBlockedError } from "@saviours/check";
6
+
7
+ export async function sendWithSavioursGuard(
8
+ to: `0x${string}`,
9
+ send: () => Promise<`0x${string}`>,
10
+ ): Promise<`0x${string}`> {
11
+ const r = await guard(to, { mode: "ens" });
12
+ if (r.decision === "WARN") {
13
+ console.warn(`[saviours] WARN ${r.ensName} — reduce size`);
14
+ }
15
+ try {
16
+ return await send();
17
+ } catch (e) {
18
+ if (e instanceof SavioursBlockedError) throw e;
19
+ throw e;
20
+ }
21
+ }
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "@saviours/check",
3
+ "version": "0.1.0",
4
+ "description": "Two-line counterparty check — ENS first, optional Shield/investigate gateway",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "SAVIOURS",
8
+ "homepage": "https://www.saviours.xyz",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/devhb1/Saviour.git",
12
+ "directory": "packages/check"
13
+ },
14
+ "bugs": {
15
+ "url": "https://github.com/devhb1/Saviour/issues"
16
+ },
17
+ "keywords": [
18
+ "ethereum",
19
+ "ens",
20
+ "security",
21
+ "wallet",
22
+ "agent",
23
+ "saviours"
24
+ ],
25
+ "publishConfig": {
26
+ "access": "public"
27
+ },
28
+ "exports": {
29
+ ".": {
30
+ "types": "./dist/index.d.ts",
31
+ "import": "./dist/index.js"
32
+ },
33
+ "./react": {
34
+ "types": "./dist/react.d.ts",
35
+ "import": "./dist/react.js"
36
+ }
37
+ },
38
+ "files": [
39
+ "dist",
40
+ "examples",
41
+ "README.md"
42
+ ],
43
+ "scripts": {
44
+ "build": "tsc -p tsconfig.json",
45
+ "typecheck": "tsc -p tsconfig.json --noEmit",
46
+ "prepare": "tsc -p tsconfig.json",
47
+ "prepublishOnly": "tsc -p tsconfig.json"
48
+ },
49
+ "peerDependencies": {
50
+ "react": ">=18"
51
+ },
52
+ "peerDependenciesMeta": {
53
+ "react": {
54
+ "optional": true
55
+ }
56
+ },
57
+ "dependencies": {
58
+ "viem": "^2.56.3"
59
+ },
60
+ "devDependencies": {
61
+ "typescript": "^5.7.2"
62
+ },
63
+ "engines": {
64
+ "node": ">=20"
65
+ }
66
+ }