@skeinlabs/sdk 0.1.0 → 0.2.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 +22 -2
- package/dist/attest.d.ts +51 -0
- package/dist/attest.js +47 -0
- package/dist/attest.js.map +1 -0
- package/dist/index.d.ts +22 -211
- package/dist/index.js +12 -2
- package/dist/index.js.map +1 -1
- package/dist/types-B_RIoOCq.d.ts +219 -0
- package/package.json +6 -1
package/README.md
CHANGED
|
@@ -9,7 +9,8 @@ listing verdict for an EVM token (**APPROVE**, **REJECT**, **ESCALATE** or
|
|
|
9
9
|
- retries that reuse the idempotency key, so a retried call is never charged twice
|
|
10
10
|
- a per-call spend cap, checked **before** any payment
|
|
11
11
|
- two ways to pay: a Skein partner key, or per call through Telegraph escrow
|
|
12
|
-
-
|
|
12
|
+
- every verdict signed by Skein, checkable offline with `@skeinlabs/sdk/attest`
|
|
13
|
+
- no runtime dependencies (the Telegraph and attest entries need `viem`)
|
|
13
14
|
|
|
14
15
|
**[Read the full tutorial →](https://skeinlabs.site/tutorial)**
|
|
15
16
|
|
|
@@ -47,7 +48,8 @@ const skein = new Skein({
|
|
|
47
48
|
try {
|
|
48
49
|
const v = await skein.verdict({
|
|
49
50
|
subject: { chainId: 8453, token: "0x…" },
|
|
50
|
-
policy: "dex-list@0.
|
|
51
|
+
policy: "dex-list@0.2.0",
|
|
52
|
+
context: { socialHandle: "project_handle", repoUrl: "https://github.com/org/repo" }, // optional: buys bot and code checks
|
|
51
53
|
onEvent: (e) => console.log(e.type), // plan, purchase, finding, decision, done
|
|
52
54
|
});
|
|
53
55
|
if (v.verdict !== "APPROVE") console.log("needs a human:", v.reasons.map((r) => r.detail));
|
|
@@ -79,6 +81,24 @@ const v = await skein.verdict({ subject: { chainId: 1, token: "0x…" } });
|
|
|
79
81
|
console.log(v.verdict, v.payment); // { rail: "telegraph", minerId, amountUsdc, receiptHash, signalHash }
|
|
80
82
|
```
|
|
81
83
|
|
|
84
|
+
## Check Skein's signature yourself
|
|
85
|
+
|
|
86
|
+
Every verdict is signed by Skein (EIP-191) over its id, subject, outcome,
|
|
87
|
+
policy, verdict hash, receipts root and cost. The signer's address is published
|
|
88
|
+
at `https://api.skeinlabs.site/v1/status` (`attester`). The check rebuilds the
|
|
89
|
+
message from the verdict's own fields, so an edited verdict fails even with the
|
|
90
|
+
original signature attached:
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
import { verifyAttestation } from "@skeinlabs/sdk/attest"; // needs viem
|
|
94
|
+
|
|
95
|
+
const { attester } = await (await fetch("https://api.skeinlabs.site/v1/status")).json();
|
|
96
|
+
const check = await verifyAttestation(v, { signer: attester });
|
|
97
|
+
if (!check.ok) throw new Error(check.problems.join("; "));
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Pin the attester address in your own config rather than fetching it on every call.
|
|
101
|
+
|
|
82
102
|
## API
|
|
83
103
|
|
|
84
104
|
| Method | Cost | What it does |
|
package/dist/attest.d.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { A as Attestation } from './types-B_RIoOCq.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The message Skein signs for every verdict (EIP-191 personal_sign, the same
|
|
5
|
+
* scheme Telegraph uses for escrow payments). It names everything a reader
|
|
6
|
+
* relies on (the subject, the outcome, the policy and engine, the verdict hash
|
|
7
|
+
* and the receipts' Merkle root, the cost) in plain lines, so a signature can
|
|
8
|
+
* travel with a listing memo or a payment and be checked by anyone who knows
|
|
9
|
+
* Skein's published attester address. Nothing secret, no dependencies: the API
|
|
10
|
+
* signs it and @skeinlabs/sdk/attest rebuilds it to verify.
|
|
11
|
+
*/
|
|
12
|
+
interface AttestedVerdict {
|
|
13
|
+
id: string;
|
|
14
|
+
subject: {
|
|
15
|
+
chainId: number;
|
|
16
|
+
token: string;
|
|
17
|
+
};
|
|
18
|
+
verdict: string;
|
|
19
|
+
riskBps: number;
|
|
20
|
+
confidenceBps: number;
|
|
21
|
+
policy: {
|
|
22
|
+
id: string;
|
|
23
|
+
version: string;
|
|
24
|
+
};
|
|
25
|
+
engineVersion: string;
|
|
26
|
+
verdictHash: string;
|
|
27
|
+
bom: {
|
|
28
|
+
root: string;
|
|
29
|
+
};
|
|
30
|
+
cost: {
|
|
31
|
+
priceUsdc: number;
|
|
32
|
+
upstreamUsdc: number;
|
|
33
|
+
};
|
|
34
|
+
network: string;
|
|
35
|
+
createdAt: string;
|
|
36
|
+
}
|
|
37
|
+
declare function attestationMessage(v: AttestedVerdict): string;
|
|
38
|
+
|
|
39
|
+
interface AttestationCheck {
|
|
40
|
+
ok: boolean;
|
|
41
|
+
/** Who signed it, as the verdict claims. */
|
|
42
|
+
signer: string | null;
|
|
43
|
+
problems: string[];
|
|
44
|
+
}
|
|
45
|
+
declare function verifyAttestation(v: AttestedVerdict & {
|
|
46
|
+
attestation?: Attestation | null;
|
|
47
|
+
}, opts: {
|
|
48
|
+
signer: string;
|
|
49
|
+
}): Promise<AttestationCheck>;
|
|
50
|
+
|
|
51
|
+
export { type AttestationCheck, type AttestedVerdict, attestationMessage, verifyAttestation };
|
package/dist/attest.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// src/attest.ts
|
|
2
|
+
import { verifyMessage } from "viem";
|
|
3
|
+
|
|
4
|
+
// ../engine/src/attest.ts
|
|
5
|
+
var ATTESTATION_TITLE = "Skein verdict attestation v1";
|
|
6
|
+
function attestationMessage(v) {
|
|
7
|
+
return [
|
|
8
|
+
ATTESTATION_TITLE,
|
|
9
|
+
`id: ${v.id}`,
|
|
10
|
+
`subject: eip155:${v.subject.chainId}:${v.subject.token.toLowerCase()}`,
|
|
11
|
+
`verdict: ${v.verdict}`,
|
|
12
|
+
`risk_bps: ${v.riskBps}`,
|
|
13
|
+
`confidence_bps: ${v.confidenceBps}`,
|
|
14
|
+
`policy: ${v.policy.id}@${v.policy.version}`,
|
|
15
|
+
`engine: ${v.engineVersion}`,
|
|
16
|
+
`verdict_hash: ${v.verdictHash}`,
|
|
17
|
+
`bom_root: ${v.bom.root}`,
|
|
18
|
+
`price_usdc: ${v.cost.priceUsdc}`,
|
|
19
|
+
`upstream_usdc: ${v.cost.upstreamUsdc}`,
|
|
20
|
+
`network: ${v.network}`,
|
|
21
|
+
`created_at: ${v.createdAt}`
|
|
22
|
+
].join("\n");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// src/attest.ts
|
|
26
|
+
async function verifyAttestation(v, opts) {
|
|
27
|
+
const a = v.attestation;
|
|
28
|
+
if (!a) return { ok: false, signer: null, problems: ["the verdict carries no attestation (the API has no attestation key set)"] };
|
|
29
|
+
const problems = [];
|
|
30
|
+
if (a.scheme !== "eip191") problems.push(`unknown scheme ${a.scheme}`);
|
|
31
|
+
if (a.signer.toLowerCase() !== opts.signer.toLowerCase()) problems.push(`signed by ${a.signer}, not the expected ${opts.signer}`);
|
|
32
|
+
const rebuilt = attestationMessage(v);
|
|
33
|
+
if (rebuilt !== a.message) problems.push("the signed message does not match the verdict's fields");
|
|
34
|
+
let valid = false;
|
|
35
|
+
try {
|
|
36
|
+
valid = await verifyMessage({ address: opts.signer, message: rebuilt, signature: a.signature });
|
|
37
|
+
} catch {
|
|
38
|
+
valid = false;
|
|
39
|
+
}
|
|
40
|
+
if (!valid) problems.push("the signature does not recover to the expected signer for this verdict");
|
|
41
|
+
return { ok: problems.length === 0, signer: a.signer, problems };
|
|
42
|
+
}
|
|
43
|
+
export {
|
|
44
|
+
attestationMessage,
|
|
45
|
+
verifyAttestation
|
|
46
|
+
};
|
|
47
|
+
//# sourceMappingURL=attest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/attest.ts","../../engine/src/attest.ts"],"sourcesContent":["/**\n * Check a Skein verdict's signature yourself (needs viem). Import from\n * \"@skeinlabs/sdk/attest\".\n *\n * import { verifyAttestation } from \"@skeinlabs/sdk/attest\";\n * const r = await verifyAttestation(v, { signer: SKEIN_ATTESTER }); // the address at /v1/status\n * if (!r.ok) throw new Error(r.problems.join(\"; \"));\n *\n * It rebuilds the signed message from the verdict's own fields, so a verdict\n * whose outcome, hash, cost or subject was edited after signing fails, even\n * when the attached message and signature are left untouched.\n */\nimport { verifyMessage } from \"viem\";\nimport { attestationMessage, type AttestedVerdict } from \"@skein/engine/attest\";\nimport type { Attestation } from \"./types\";\n\nexport { attestationMessage, type AttestedVerdict };\n\nexport interface AttestationCheck {\n ok: boolean;\n /** Who signed it, as the verdict claims. */\n signer: string | null;\n problems: string[];\n}\n\nexport async function verifyAttestation(v: AttestedVerdict & { attestation?: Attestation | null }, opts: { signer: string }): Promise<AttestationCheck> {\n const a = v.attestation;\n if (!a) return { ok: false, signer: null, problems: [\"the verdict carries no attestation (the API has no attestation key set)\"] };\n const problems: string[] = [];\n if (a.scheme !== \"eip191\") problems.push(`unknown scheme ${a.scheme}`);\n if (a.signer.toLowerCase() !== opts.signer.toLowerCase()) problems.push(`signed by ${a.signer}, not the expected ${opts.signer}`);\n const rebuilt = attestationMessage(v);\n if (rebuilt !== a.message) problems.push(\"the signed message does not match the verdict's fields\");\n let valid = false;\n try {\n valid = await verifyMessage({ address: opts.signer as `0x${string}`, message: rebuilt, signature: a.signature as `0x${string}` });\n } catch {\n valid = false;\n }\n if (!valid) problems.push(\"the signature does not recover to the expected signer for this verdict\");\n return { ok: problems.length === 0, signer: a.signer, problems };\n}\n","/**\n * The message Skein signs for every verdict (EIP-191 personal_sign, the same\n * scheme Telegraph uses for escrow payments). It names everything a reader\n * relies on (the subject, the outcome, the policy and engine, the verdict hash\n * and the receipts' Merkle root, the cost) in plain lines, so a signature can\n * travel with a listing memo or a payment and be checked by anyone who knows\n * Skein's published attester address. Nothing secret, no dependencies: the API\n * signs it and @skeinlabs/sdk/attest rebuilds it to verify.\n */\nexport interface AttestedVerdict {\n id: string;\n subject: { chainId: number; token: string };\n verdict: string;\n riskBps: number;\n confidenceBps: number;\n policy: { id: string; version: string };\n engineVersion: string;\n verdictHash: string;\n bom: { root: string };\n cost: { priceUsdc: number; upstreamUsdc: number };\n network: string;\n createdAt: string;\n}\n\nexport const ATTESTATION_SCHEME = \"eip191\";\nexport const ATTESTATION_TITLE = \"Skein verdict attestation v1\";\n\nexport function attestationMessage(v: AttestedVerdict): string {\n return [\n ATTESTATION_TITLE,\n `id: ${v.id}`,\n `subject: eip155:${v.subject.chainId}:${v.subject.token.toLowerCase()}`,\n `verdict: ${v.verdict}`,\n `risk_bps: ${v.riskBps}`,\n `confidence_bps: ${v.confidenceBps}`,\n `policy: ${v.policy.id}@${v.policy.version}`,\n `engine: ${v.engineVersion}`,\n `verdict_hash: ${v.verdictHash}`,\n `bom_root: ${v.bom.root}`,\n `price_usdc: ${v.cost.priceUsdc}`,\n `upstream_usdc: ${v.cost.upstreamUsdc}`,\n `network: ${v.network}`,\n `created_at: ${v.createdAt}`,\n ].join(\"\\n\");\n}\n\nexport interface Attestation {\n scheme: typeof ATTESTATION_SCHEME;\n signer: string;\n message: string;\n signature: string;\n}\n"],"mappings":";AAYA,SAAS,qBAAqB;;;ACavB,IAAM,oBAAoB;AAE1B,SAAS,mBAAmB,GAA4B;AAC7D,SAAO;AAAA,IACL;AAAA,IACA,OAAO,EAAE,EAAE;AAAA,IACX,mBAAmB,EAAE,QAAQ,OAAO,IAAI,EAAE,QAAQ,MAAM,YAAY,CAAC;AAAA,IACrE,YAAY,EAAE,OAAO;AAAA,IACrB,aAAa,EAAE,OAAO;AAAA,IACtB,mBAAmB,EAAE,aAAa;AAAA,IAClC,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,OAAO;AAAA,IAC1C,WAAW,EAAE,aAAa;AAAA,IAC1B,iBAAiB,EAAE,WAAW;AAAA,IAC9B,aAAa,EAAE,IAAI,IAAI;AAAA,IACvB,eAAe,EAAE,KAAK,SAAS;AAAA,IAC/B,kBAAkB,EAAE,KAAK,YAAY;AAAA,IACrC,YAAY,EAAE,OAAO;AAAA,IACrB,eAAe,EAAE,SAAS;AAAA,EAC5B,EAAE,KAAK,IAAI;AACb;;;ADnBA,eAAsB,kBAAkB,GAA2D,MAAqD;AACtJ,QAAM,IAAI,EAAE;AACZ,MAAI,CAAC,EAAG,QAAO,EAAE,IAAI,OAAO,QAAQ,MAAM,UAAU,CAAC,yEAAyE,EAAE;AAChI,QAAM,WAAqB,CAAC;AAC5B,MAAI,EAAE,WAAW,SAAU,UAAS,KAAK,kBAAkB,EAAE,MAAM,EAAE;AACrE,MAAI,EAAE,OAAO,YAAY,MAAM,KAAK,OAAO,YAAY,EAAG,UAAS,KAAK,aAAa,EAAE,MAAM,sBAAsB,KAAK,MAAM,EAAE;AAChI,QAAM,UAAU,mBAAmB,CAAC;AACpC,MAAI,YAAY,EAAE,QAAS,UAAS,KAAK,wDAAwD;AACjG,MAAI,QAAQ;AACZ,MAAI;AACF,YAAQ,MAAM,cAAc,EAAE,SAAS,KAAK,QAAyB,SAAS,SAAS,WAAW,EAAE,UAA2B,CAAC;AAAA,EAClI,QAAQ;AACN,YAAQ;AAAA,EACV;AACA,MAAI,CAAC,MAAO,UAAS,KAAK,wEAAwE;AAClG,SAAO,EAAE,IAAI,SAAS,WAAW,GAAG,QAAQ,EAAE,QAAQ,SAAS;AACjE;","names":[]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,207 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
interface Subject {
|
|
4
|
-
chainId: number;
|
|
5
|
-
token: string;
|
|
6
|
-
}
|
|
7
|
-
interface Finding {
|
|
8
|
-
check: string;
|
|
9
|
-
status: CheckStatus;
|
|
10
|
-
severity: number;
|
|
11
|
-
metric?: string;
|
|
12
|
-
value?: number;
|
|
13
|
-
unit?: string;
|
|
14
|
-
confidence: number;
|
|
15
|
-
sourceGroup: string;
|
|
16
|
-
evidence?: {
|
|
17
|
-
receiptHash?: string;
|
|
18
|
-
signalHash?: string;
|
|
19
|
-
minerId?: string;
|
|
20
|
-
};
|
|
21
|
-
notes: string[];
|
|
22
|
-
}
|
|
23
|
-
/** The verdict object (build spec, section 6). */
|
|
24
|
-
interface VerdictObject {
|
|
25
|
-
id: string;
|
|
26
|
-
verdict: Verdict;
|
|
27
|
-
verdictCode: number;
|
|
28
|
-
riskBps: number;
|
|
29
|
-
confidenceBps: number;
|
|
30
|
-
coverage: number;
|
|
31
|
-
summary: string;
|
|
32
|
-
reasons: {
|
|
33
|
-
code: string;
|
|
34
|
-
check?: string;
|
|
35
|
-
detail: string;
|
|
36
|
-
}[];
|
|
37
|
-
openRisks: string[];
|
|
38
|
-
conflicts: string[];
|
|
39
|
-
subject: Subject;
|
|
40
|
-
findings: Finding[];
|
|
41
|
-
cost: {
|
|
42
|
-
upstreamUsdc: number;
|
|
43
|
-
priceUsdc: number;
|
|
44
|
-
currency: string;
|
|
45
|
-
};
|
|
46
|
-
bom: {
|
|
47
|
-
root: string;
|
|
48
|
-
items: number;
|
|
49
|
-
};
|
|
50
|
-
policy: {
|
|
51
|
-
id: string;
|
|
52
|
-
version: string;
|
|
53
|
-
};
|
|
54
|
-
engineVersion: string;
|
|
55
|
-
verdictHash: string;
|
|
56
|
-
channel: string;
|
|
57
|
-
network: string;
|
|
58
|
-
createdAt: string;
|
|
59
|
-
durationMs: number;
|
|
60
|
-
disclaimer: string;
|
|
61
|
-
cached?: boolean;
|
|
62
|
-
replayed?: boolean;
|
|
63
|
-
}
|
|
64
|
-
interface Quote {
|
|
65
|
-
subject: Subject;
|
|
66
|
-
policy: string;
|
|
67
|
-
priceUsdc: number;
|
|
68
|
-
ok: boolean;
|
|
69
|
-
upstreamUsdc?: number;
|
|
70
|
-
checks?: {
|
|
71
|
-
check: string;
|
|
72
|
-
intent: string;
|
|
73
|
-
quoteUsdc: number;
|
|
74
|
-
}[];
|
|
75
|
-
dropped?: unknown[];
|
|
76
|
-
refusal?: {
|
|
77
|
-
code: string;
|
|
78
|
-
detail: string;
|
|
79
|
-
checks?: string[];
|
|
80
|
-
quoteUusdc?: number;
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
interface VerifyReport {
|
|
84
|
-
id: string;
|
|
85
|
-
ok: boolean;
|
|
86
|
-
checks: Record<string, boolean>;
|
|
87
|
-
verdictHash: {
|
|
88
|
-
stored: string;
|
|
89
|
-
recomputed: string;
|
|
90
|
-
};
|
|
91
|
-
bomRoot: {
|
|
92
|
-
stored: string;
|
|
93
|
-
recomputed: string;
|
|
94
|
-
};
|
|
95
|
-
receipts: string[];
|
|
96
|
-
problems: string[];
|
|
97
|
-
}
|
|
98
|
-
interface BomLine {
|
|
99
|
-
check: string;
|
|
100
|
-
intent: string;
|
|
101
|
-
minerId: string | null;
|
|
102
|
-
minerName: string | null;
|
|
103
|
-
receiptHash: string | null;
|
|
104
|
-
signalHash: string | null;
|
|
105
|
-
amountUsdc: number;
|
|
106
|
-
billed: boolean;
|
|
107
|
-
error: string | null;
|
|
108
|
-
[k: string]: unknown;
|
|
109
|
-
}
|
|
110
|
-
interface Bom {
|
|
111
|
-
id: string;
|
|
112
|
-
root: string;
|
|
113
|
-
items: number;
|
|
114
|
-
verdictHash: string;
|
|
115
|
-
lines: BomLine[];
|
|
116
|
-
}
|
|
117
|
-
/** One server-sent event of a running verdict. */
|
|
118
|
-
type VerdictEvent = {
|
|
119
|
-
type: "plan";
|
|
120
|
-
data: {
|
|
121
|
-
purchases?: {
|
|
122
|
-
check: string;
|
|
123
|
-
intent: string;
|
|
124
|
-
quoteUusdc: number;
|
|
125
|
-
}[];
|
|
126
|
-
dropped?: unknown[];
|
|
127
|
-
[k: string]: unknown;
|
|
128
|
-
};
|
|
129
|
-
} | {
|
|
130
|
-
type: "purchase";
|
|
131
|
-
data: {
|
|
132
|
-
check: string;
|
|
133
|
-
minerId?: string;
|
|
134
|
-
minerName?: string;
|
|
135
|
-
amountUusdc: number;
|
|
136
|
-
receiptHash?: string;
|
|
137
|
-
error?: string;
|
|
138
|
-
[k: string]: unknown;
|
|
139
|
-
};
|
|
140
|
-
} | {
|
|
141
|
-
type: "finding";
|
|
142
|
-
data: Finding;
|
|
143
|
-
} | {
|
|
144
|
-
type: "decision";
|
|
145
|
-
data: {
|
|
146
|
-
decision: {
|
|
147
|
-
verdict: Verdict;
|
|
148
|
-
riskBps: number;
|
|
149
|
-
[k: string]: unknown;
|
|
150
|
-
};
|
|
151
|
-
verdictHash: string;
|
|
152
|
-
[k: string]: unknown;
|
|
153
|
-
};
|
|
154
|
-
} | {
|
|
155
|
-
type: "done";
|
|
156
|
-
data: {
|
|
157
|
-
id?: string;
|
|
158
|
-
[k: string]: unknown;
|
|
159
|
-
};
|
|
160
|
-
} | {
|
|
161
|
-
type: "refused";
|
|
162
|
-
data: {
|
|
163
|
-
code: string;
|
|
164
|
-
detail: string;
|
|
165
|
-
[k: string]: unknown;
|
|
166
|
-
};
|
|
167
|
-
} | {
|
|
168
|
-
type: "error";
|
|
169
|
-
data: {
|
|
170
|
-
message: string;
|
|
171
|
-
[k: string]: unknown;
|
|
172
|
-
};
|
|
173
|
-
};
|
|
174
|
-
/** The Telegraph ask result of a paid call, as returned by any Telegraph client. */
|
|
175
|
-
interface TelegraphAskOutcomeOk {
|
|
176
|
-
ok: true;
|
|
177
|
-
response: {
|
|
178
|
-
miner_id: string;
|
|
179
|
-
result: unknown;
|
|
180
|
-
signal_hash?: string;
|
|
181
|
-
cost_usd?: number;
|
|
182
|
-
};
|
|
183
|
-
receipt: {
|
|
184
|
-
receipt_hash: string;
|
|
185
|
-
} | null;
|
|
186
|
-
amountUusdc: number;
|
|
187
|
-
durationMs: number;
|
|
188
|
-
}
|
|
189
|
-
interface TelegraphAskOutcomeFail {
|
|
190
|
-
ok: false;
|
|
191
|
-
kind: string;
|
|
192
|
-
error: string;
|
|
193
|
-
httpStatus?: number;
|
|
194
|
-
}
|
|
195
|
-
/** Anything that can make one paid Telegraph ask, e.g. TelegraphClient from @skeinlabs/sdk/telegraph. */
|
|
196
|
-
interface TelegraphAsker {
|
|
197
|
-
ask(req: {
|
|
198
|
-
intent: string;
|
|
199
|
-
params?: Record<string, unknown>;
|
|
200
|
-
}, opts: {
|
|
201
|
-
minerId?: string;
|
|
202
|
-
timeoutMs: number;
|
|
203
|
-
}): Promise<TelegraphAskOutcomeOk | TelegraphAskOutcomeFail>;
|
|
204
|
-
}
|
|
1
|
+
import { T as TelegraphAsker, S as Subject, Q as Quote, V as VerdictObject, B as Bom, a as VerifyReport, b as VerdictEvent } from './types-B_RIoOCq.js';
|
|
2
|
+
export { A as Attestation, c as BomLine, C as CheckStatus, F as Finding, d as TelegraphAskOutcomeFail, e as TelegraphAskOutcomeOk, f as Verdict } from './types-B_RIoOCq.js';
|
|
205
3
|
|
|
206
4
|
/** One parsed server-sent event. */
|
|
207
5
|
interface RawEvent {
|
|
@@ -254,12 +52,12 @@ interface VerdictRequest {
|
|
|
254
52
|
subject: Subject;
|
|
255
53
|
/** "dex-list@0.1.0", or an id for its latest version. */
|
|
256
54
|
policy?: string;
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
55
|
+
/**
|
|
56
|
+
* Optional evidence about the project. socialHandle buys the social-bot
|
|
57
|
+
* check, repoUrl (github.com or gitlab.com) buys the code review.
|
|
58
|
+
* `social` and `repo` are accepted as aliases.
|
|
59
|
+
*/
|
|
60
|
+
context?: VerdictContextInput;
|
|
263
61
|
/** Reuse to make a retried call return the original verdict. Generated when omitted. */
|
|
264
62
|
idempotencyKey?: string;
|
|
265
63
|
/** Called with each live event (API key path). */
|
|
@@ -268,6 +66,19 @@ interface VerdictRequest {
|
|
|
268
66
|
/** A quote you already fetched for this request, so verdict() does not fetch another. */
|
|
269
67
|
quote?: Quote;
|
|
270
68
|
}
|
|
69
|
+
interface VerdictContextInput {
|
|
70
|
+
deployer?: string;
|
|
71
|
+
socialHandle?: string;
|
|
72
|
+
repoUrl?: string;
|
|
73
|
+
treasuryAddresses?: string[];
|
|
74
|
+
pool?: string;
|
|
75
|
+
/** Alias of socialHandle. */
|
|
76
|
+
social?: string;
|
|
77
|
+
/** Alias of repoUrl. */
|
|
78
|
+
repo?: string;
|
|
79
|
+
}
|
|
80
|
+
/** The API's field names: aliases mapped, empty values dropped. */
|
|
81
|
+
declare function canonicalContext(c: VerdictContextInput | undefined): Record<string, unknown> | undefined;
|
|
271
82
|
type Payment = {
|
|
272
83
|
rail: "apiKey";
|
|
273
84
|
} | {
|
|
@@ -373,4 +184,4 @@ declare class Skein {
|
|
|
373
184
|
private viaTelegraph;
|
|
374
185
|
}
|
|
375
186
|
|
|
376
|
-
export {
|
|
187
|
+
export { Bom, type Payer, type Payment, Quote, SKEIN_INTENT, Skein, SkeinError, type SkeinOptions, SpendCapError, Subject, TelegraphAsker, type VerdictContextInput, VerdictEvent, VerdictObject, type VerdictRequest, type VerdictResult, VerifyReport, canonicalContext, parseSse };
|
package/dist/index.js
CHANGED
|
@@ -44,6 +44,15 @@ async function* parseSse(body, signal) {
|
|
|
44
44
|
// src/index.ts
|
|
45
45
|
var SKEIN_INTENT = "FRAUD_RISK_TOKEN_LISTING";
|
|
46
46
|
var CHAIN_NAMES = { 1: "ethereum", 56: "bsc", 8453: "base", 42161: "arbitrum" };
|
|
47
|
+
function canonicalContext(c) {
|
|
48
|
+
if (!c) return void 0;
|
|
49
|
+
const { social, repo, ...rest } = c;
|
|
50
|
+
const out = { ...rest };
|
|
51
|
+
if (out.socialHandle === void 0 && social) out.socialHandle = social;
|
|
52
|
+
if (out.repoUrl === void 0 && repo) out.repoUrl = repo;
|
|
53
|
+
for (const [k, v] of Object.entries(out)) if (v === void 0 || v === "" || Array.isArray(v) && v.length === 0) delete out[k];
|
|
54
|
+
return Object.keys(out).length ? out : void 0;
|
|
55
|
+
}
|
|
47
56
|
var SkeinError = class extends Error {
|
|
48
57
|
constructor(code, message, status = 0, details, payment) {
|
|
49
58
|
super(message);
|
|
@@ -198,7 +207,7 @@ var Skein = class {
|
|
|
198
207
|
body: JSON.stringify({
|
|
199
208
|
subject: req.subject,
|
|
200
209
|
...req.policy ? { policy: req.policy } : {},
|
|
201
|
-
...req.context ? { context: req.context } : {},
|
|
210
|
+
...canonicalContext(req.context) ? { context: canonicalContext(req.context) } : {},
|
|
202
211
|
...this.opts.maxUsdcPerCall !== void 0 ? { budgetUsdcMax: this.opts.maxUsdcPerCall } : {},
|
|
203
212
|
mode: "async"
|
|
204
213
|
}),
|
|
@@ -244,7 +253,7 @@ var Skein = class {
|
|
|
244
253
|
chain: CHAIN_NAMES[req.subject.chainId] ?? String(req.subject.chainId),
|
|
245
254
|
subject: req.subject,
|
|
246
255
|
...req.policy ? { policy: req.policy } : {},
|
|
247
|
-
...req.context ? { context: req.context } : {}
|
|
256
|
+
...canonicalContext(req.context) ? { context: canonicalContext(req.context) } : {}
|
|
248
257
|
};
|
|
249
258
|
const out = await payer.client.ask({ intent: payer.intent ?? SKEIN_INTENT, params }, { ...payer.minerId ? { minerId: payer.minerId } : {}, timeoutMs: this.timeoutMs });
|
|
250
259
|
if (!out.ok) {
|
|
@@ -288,6 +297,7 @@ export {
|
|
|
288
297
|
Skein,
|
|
289
298
|
SkeinError,
|
|
290
299
|
SpendCapError,
|
|
300
|
+
canonicalContext,
|
|
291
301
|
parseSse
|
|
292
302
|
};
|
|
293
303
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/sse.ts","../src/index.ts"],"sourcesContent":["/** One parsed server-sent event. */\nexport interface RawEvent {\n event: string;\n data: string;\n id?: string;\n}\n\n/**\n * Parses a text/event-stream body into events (WHATWG rules: fields per line,\n * a blank line dispatches, \"data\" lines join with \\n, \":\" lines are comments).\n * Works on any fetch Response, in Node or the browser.\n */\nexport async function* parseSse(body: ReadableStream<Uint8Array>, signal?: AbortSignal): AsyncGenerator<RawEvent> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buf = \"\";\n let event = \"message\";\n let data: string[] = [];\n let id: string | undefined;\n const onAbort = () => void reader.cancel().catch(() => {});\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n try {\n for (;;) {\n const { value, done } = await reader.read();\n if (done) break;\n buf += decoder.decode(value, { stream: true });\n let nl: number;\n // A lone \"\\r\" at the end may be the first half of a \"\\r\\n\" split across chunks: wait for the next one.\n while ((nl = buf.search(/\\r\\n|\\r(?!$)|\\n/)) >= 0) {\n const line = buf.slice(0, nl);\n buf = buf.slice(nl + (buf.startsWith(\"\\r\\n\", nl) ? 2 : 1));\n if (line === \"\") {\n if (data.length) yield { event, data: data.join(\"\\n\"), ...(id !== undefined ? { id } : {}) };\n event = \"message\";\n data = [];\n continue;\n }\n if (line.startsWith(\":\")) continue;\n const colon = line.indexOf(\":\");\n const field = colon < 0 ? line : line.slice(0, colon);\n const value = colon < 0 ? \"\" : line.slice(colon + 1).replace(/^ /, \"\");\n if (field === \"event\") event = value;\n else if (field === \"data\") data.push(value);\n else if (field === \"id\") id = value;\n }\n }\n // A stream that ends mid-event drops it (WHATWG: an event is dispatched only by its blank line).\n } finally {\n signal?.removeEventListener(\"abort\", onAbort);\n // Stopping early (a terminal event, a break) must release the connection, not just the lock.\n await reader.cancel().catch(() => {});\n reader.releaseLock();\n }\n}\n","import { parseSse } from \"./sse\";\nimport type { Bom, Quote, Subject, TelegraphAsker, VerdictEvent, VerdictObject, VerifyReport } from \"./types\";\n\nexport * from \"./types\";\nexport { parseSse } from \"./sse\";\n\n/** The intent Skein serves on Telegraph (plan A; see miner/INTENT.md). */\nexport const SKEIN_INTENT = \"FRAUD_RISK_TOKEN_LISTING\";\n\nconst CHAIN_NAMES: Record<number, string> = { 1: \"ethereum\", 56: \"bsc\", 8453: \"base\", 42161: \"arbitrum\" };\n\n/**\n * How a verdict is paid for:\n * - apiKey: a Skein partner key against the HTTP API (free during the hackathon);\n * - telegraph: one paid Telegraph ask, routed to the Skein miner or pinned to it.\n * `client` is any Telegraph client, e.g. new TelegraphClient(...) from @skeinlabs/sdk/telegraph,\n * which enforces its own per-call price cap on the 402 challenge.\n */\nexport type Payer =\n | { kind: \"apiKey\"; key: string }\n | { kind: \"telegraph\"; client: TelegraphAsker; minerId?: string; intent?: string };\n\nexport interface SkeinOptions {\n /** e.g. https://api.skeinlabs.site (with or without /v1). */\n apiUrl: string;\n payer?: Payer;\n /** Refuse, before paying, any verdict whose quoted price is above this. */\n maxUsdcPerCall?: number;\n /** Retries for network errors, 429 and retryable 5xx. Default 2. */\n retries?: number;\n /** The most the SDK sleeps between retries of one call, in total; a longer Retry-After throws instead. Default 10 s. */\n maxRetryWaitMs?: number;\n /** Each HTTP request (submit, quote, get, verify) gives up after this. Default 15 s. */\n requestTimeoutMs?: number;\n /** How long verdict() waits for a result. Default 120 s. */\n timeoutMs?: number;\n fetch?: typeof fetch;\n}\n\nexport interface VerdictRequest {\n subject: Subject;\n /** \"dex-list@0.1.0\", or an id for its latest version. */\n policy?: string;\n context?: { deployer?: string; social?: string; repo?: string; [k: string]: unknown };\n /** Reuse to make a retried call return the original verdict. Generated when omitted. */\n idempotencyKey?: string;\n /** Called with each live event (API key path). */\n onEvent?: (e: VerdictEvent) => void;\n signal?: AbortSignal;\n /** A quote you already fetched for this request, so verdict() does not fetch another. */\n quote?: Quote;\n}\n\nexport type Payment =\n | { rail: \"apiKey\" }\n | { rail: \"telegraph\"; minerId: string; amountUsdc: number; receiptHash: string | null; signalHash: string | null };\n\nexport type VerdictResult = VerdictObject & { payment: Payment };\n\n/** Every API error, with the API's code (BUDGET_TOO_LOW, RATE_LIMITED, …) or an SDK code. */\nexport class SkeinError extends Error {\n constructor(\n readonly code: string,\n message: string,\n readonly status = 0,\n readonly details?: unknown,\n /**\n * Set when money moved (or may have) before the failure: a Telegraph ask\n * that was paid but produced no verdict. Count it against your caps.\n */\n readonly payment?: { amountUsdc: number; billing: \"paid\" | \"unknown\"; receiptHash?: string | null },\n ) {\n super(message);\n this.name = \"SkeinError\";\n }\n}\n\n/** The quoted price is above maxUsdcPerCall; nothing was paid. */\nexport class SpendCapError extends SkeinError {\n constructor(\n readonly priceUsdc: number,\n readonly capUsdc: number,\n ) {\n super(\"SPEND_CAP\", `quoted ${priceUsdc} USDC is above the cap of ${capUsdc} USDC; nothing was paid`);\n this.name = \"SpendCapError\";\n }\n}\n\n/** Refusals that will not change on retry. */\nconst FINAL = new Set([\"UPSTREAM_UNAVAILABLE\", \"DAILY_CAP_REACHED\", \"MARGIN_GUARD\", \"SELF_ROUTING\", \"BUDGET_TOO_LOW\"]);\nconst sleep = (ms: number, signal?: AbortSignal) =>\n new Promise<void>((resolve, reject) => {\n const t = setTimeout(resolve, ms);\n signal?.addEventListener(\"abort\", () => (clearTimeout(t), reject(signal.reason)), { once: true });\n });\n\nexport class Skein {\n private readonly base: string;\n private readonly fetch: typeof fetch;\n private readonly retries: number;\n private readonly timeoutMs: number;\n\n constructor(private readonly opts: SkeinOptions) {\n this.base = opts.apiUrl.replace(/\\/$/, \"\").replace(/\\/v1$/, \"\");\n this.fetch = opts.fetch ?? ((...a) => globalThis.fetch(...a));\n this.retries = opts.retries ?? 2;\n this.timeoutMs = opts.timeoutMs ?? 120_000;\n this.maxRetryWaitMs = opts.maxRetryWaitMs ?? 10_000;\n this.requestTimeoutMs = opts.requestTimeoutMs ?? 15_000;\n }\n\n private readonly maxRetryWaitMs: number;\n private readonly requestTimeoutMs: number;\n\n /** One HTTP request with its own deadline, still cancellable by the caller's signal. */\n private async request(url: string, init: RequestInit): Promise<{ res: Response; json: unknown }> {\n const ctl = new AbortController();\n const timer = setTimeout(() => ctl.abort(new DOMException(\"request timed out\", \"TimeoutError\")), this.requestTimeoutMs);\n const onAbort = () => ctl.abort(init.signal?.reason);\n init.signal?.addEventListener(\"abort\", onAbort, { once: true });\n try {\n const res = await this.fetch(url, { ...init, signal: ctl.signal });\n const json = await res.json().catch(() => null);\n return { res, json };\n } finally {\n clearTimeout(timer);\n init.signal?.removeEventListener(\"abort\", onAbort);\n }\n }\n\n /**\n * A raw call with typed errors and retries. POSTs are retried only with an\n * idempotency key. Retries sleep at most maxRetryWaitMs in total: a\n * Retry-After past that (a daily cap until midnight) throws at once.\n */\n private async call<T>(path: string, init: RequestInit = {}, retryable = (init.method ?? \"GET\") === \"GET\"): Promise<{ status: number; body: T }> {\n let waited = 0;\n for (let attempt = 0; ; attempt++) {\n let res: Response;\n let json: (T & { error?: { code: string; message: string; details?: unknown } }) | null;\n try {\n ({ res, json } = (await this.request(`${this.base}${path}`, init)) as { res: Response; json: typeof json });\n } catch (e) {\n if (init.signal?.aborted) throw e;\n const backoff = 500 * 2 ** attempt;\n if (retryable && attempt < this.retries && waited + backoff <= this.maxRetryWaitMs) {\n waited += backoff;\n await sleep(backoff, init.signal ?? undefined);\n continue;\n }\n const timedOut = (e as Error).name === \"TimeoutError\";\n throw new SkeinError(timedOut ? \"TIMEOUT\" : \"NETWORK\", timedOut ? `no answer from Skein in ${this.requestTimeoutMs} ms` : `could not reach Skein: ${(e as Error).message}`);\n }\n if (res.ok) return { status: res.status, body: json as T };\n const err = json?.error ?? { code: `HTTP_${res.status}`, message: res.statusText || `HTTP ${res.status}` };\n const after = Number(res.headers.get(\"retry-after\"));\n const wait = Number.isFinite(after) && after > 0 ? after * 1000 : 500 * 2 ** attempt;\n const again = retryable && attempt < this.retries && (res.status === 429 || (res.status >= 500 && !FINAL.has(err.code))) && waited + wait <= this.maxRetryWaitMs;\n if (!again) throw new SkeinError(err.code, err.message, res.status, err.details);\n waited += wait;\n await sleep(wait, init.signal ?? undefined);\n }\n }\n\n /** What a verdict would buy and cost, without buying. Free. */\n async quote(req: { subject: Subject; policy?: string }): Promise<Quote> {\n const q = new URLSearchParams({ chain: String(req.subject.chainId), token: req.subject.token });\n if (req.policy) q.set(\"policy\", req.policy);\n return (await this.call<Quote>(`/v1/quote?${q}`)).body;\n }\n\n /** A stored verdict, or { status: \"running\" } while it is being made. */\n async get(id: string): Promise<VerdictObject | { id: string; status: \"running\" }> {\n return (await this.call<VerdictObject | { id: string; status: \"running\" }>(`/v1/verdicts/${encodeURIComponent(id)}`)).body;\n }\n\n /** The bill of materials: every paid input and its receipt. */\n async bom(id: string): Promise<Bom> {\n return (await this.call<Bom>(`/v1/verdicts/${encodeURIComponent(id)}/bom`)).body;\n }\n\n /** Recompute a verdict from its raw paid answers. */\n async verify(id: string): Promise<VerifyReport> {\n return (\n await this.call<VerifyReport>(\"/v1/verify\", { method: \"POST\", headers: { \"content-type\": \"application/json\" }, body: JSON.stringify({ id }) }, true)\n ).body;\n }\n\n /** The live events of a verdict, replayed from the start; ends after done, refused or error. */\n async *stream(id: string, opts: { signal?: AbortSignal } = {}): AsyncGenerator<VerdictEvent> {\n const res = await this.fetch(`${this.base}/v1/verdicts/${encodeURIComponent(id)}/events`, {\n headers: { accept: \"text/event-stream\" },\n ...(opts.signal ? { signal: opts.signal } : {}),\n });\n if (!res.ok || !res.body) throw new SkeinError(`HTTP_${res.status}`, `event stream failed: HTTP ${res.status}`, res.status);\n for await (const raw of parseSse(res.body, opts.signal)) {\n let data: unknown;\n try {\n data = JSON.parse(raw.data);\n } catch {\n continue;\n }\n const e = { type: raw.event, data } as VerdictEvent;\n yield e;\n if (e.type === \"done\" || e.type === \"refused\" || e.type === \"error\") return;\n }\n }\n\n /**\n * Buys one verdict and returns it once it is sealed. With maxUsdcPerCall\n * set, the price is quoted first and the call refused before any payment.\n */\n async verdict(req: VerdictRequest): Promise<VerdictResult> {\n const payer = this.opts.payer;\n if (!payer) throw new SkeinError(\"NO_PAYER\", \"verdict() needs a payer: { kind: 'apiKey', key } or { kind: 'telegraph', client }\");\n if (this.opts.maxUsdcPerCall !== undefined) {\n const q = req.quote ?? (await this.quote({ subject: req.subject, ...(req.policy ? { policy: req.policy } : {}) }));\n if (!q.ok && q.refusal) throw new SkeinError(q.refusal.code, q.refusal.detail, q.refusal.code === \"BUDGET_TOO_LOW\" ? 422 : 503, q.refusal);\n if (q.priceUsdc > this.opts.maxUsdcPerCall) throw new SpendCapError(q.priceUsdc, this.opts.maxUsdcPerCall);\n }\n return payer.kind === \"apiKey\" ? this.viaApi(req) : this.viaTelegraph(payer, req);\n }\n\n /**\n * Starts a verdict on the partner-key rail and returns at once: the id while\n * it runs, or the verdict itself when it is cached or replayed. Pair with\n * wait(id). Spend-cap checks are the caller's (verdict() does them).\n */\n async submit(req: VerdictRequest): Promise<{ id: string; status: \"running\" } | VerdictResult> {\n const payer = this.opts.payer;\n if (payer?.kind !== \"apiKey\") throw new SkeinError(\"NO_PAYER\", \"submit() needs an apiKey payer\");\n const { status, body } = await this.call<VerdictObject | { id: string; status: \"running\" }>(\n \"/v1/verdicts\",\n {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", authorization: `Bearer ${payer.key}`, \"idempotency-key\": req.idempotencyKey ?? crypto.randomUUID() },\n body: JSON.stringify({\n subject: req.subject,\n ...(req.policy ? { policy: req.policy } : {}),\n ...(req.context ? { context: req.context } : {}),\n ...(this.opts.maxUsdcPerCall !== undefined ? { budgetUsdcMax: this.opts.maxUsdcPerCall } : {}),\n mode: \"async\",\n }),\n ...(req.signal ? { signal: req.signal } : {}),\n },\n true,\n );\n return status === 202 ? (body as { id: string; status: \"running\" }) : { ...(body as VerdictObject), payment: { rail: \"apiKey\" } };\n }\n\n /**\n * Waits for a submitted verdict: follows its event stream (falling back to\n * polling if the stream drops) and throws a SkeinError if it is refused.\n */\n async wait(id: string, opts: { onEvent?: (e: VerdictEvent) => void; signal?: AbortSignal; timeoutMs?: number } = {}): Promise<VerdictResult> {\n const deadline = Date.now() + (opts.timeoutMs ?? this.timeoutMs);\n const timeout = AbortSignal.timeout(Math.max(1, deadline - Date.now()));\n const signal = opts.signal ? AbortSignal.any([opts.signal, timeout]) : timeout;\n try {\n for await (const e of this.stream(id, { signal })) {\n opts.onEvent?.(e);\n if (e.type === \"refused\") throw new SkeinError(e.data.code, e.data.detail, e.data.code === \"BUDGET_TOO_LOW\" ? 422 : 503, e.data);\n if (e.type === \"error\") throw new SkeinError(\"VERDICT_FAILED\", e.data.message, 503);\n }\n } catch (e) {\n if (e instanceof SkeinError && !e.code.startsWith(\"HTTP_\")) throw e;\n if (opts.signal?.aborted) throw e;\n // The stream dropped or timed out: fall back to polling until the deadline.\n }\n for (;;) {\n const v = await this.get(id);\n if (!(\"status\" in v && v.status === \"running\")) return { ...(v as VerdictObject), payment: { rail: \"apiKey\" } };\n if (Date.now() >= deadline) throw new SkeinError(\"TIMEOUT\", `verdict ${id} is still running; call wait(id) again`, 504, { id });\n await sleep(Math.min(1000, Math.max(0, deadline - Date.now())), opts.signal);\n }\n }\n\n private async viaApi(req: VerdictRequest): Promise<VerdictResult> {\n const started = await this.submit(req);\n if (!(\"status\" in started && started.status === \"running\")) return started as VerdictResult;\n return this.wait(started.id, { ...(req.onEvent ? { onEvent: req.onEvent } : {}), ...(req.signal ? { signal: req.signal } : {}) });\n }\n\n private async viaTelegraph(payer: Extract<Payer, { kind: \"telegraph\" }>, req: VerdictRequest): Promise<VerdictResult> {\n const params = {\n token: req.subject.token,\n chain: CHAIN_NAMES[req.subject.chainId] ?? String(req.subject.chainId),\n subject: req.subject,\n ...(req.policy ? { policy: req.policy } : {}),\n ...(req.context ? { context: req.context } : {}),\n };\n const out = await payer.client.ask({ intent: payer.intent ?? SKEIN_INTENT, params }, { ...(payer.minerId ? { minerId: payer.minerId } : {}), timeoutMs: this.timeoutMs });\n if (!out.ok) {\n const paidUusdc = (out as { paidUusdc?: number }).paidUusdc ?? 0;\n throw new SkeinError(\n `TELEGRAPH_${out.kind.toUpperCase()}`,\n out.error,\n out.httpStatus ?? 0,\n undefined,\n paidUusdc > 0 ? { amountUsdc: paidUusdc / 1e6, billing: \"unknown\" } : undefined,\n );\n }\n const payment: Payment = {\n rail: \"telegraph\",\n minerId: out.response.miner_id,\n amountUsdc: out.amountUusdc / 1e6,\n receiptHash: out.receipt?.receipt_hash ?? null,\n signalHash: out.response.signal_hash ?? null,\n };\n const paid = { amountUsdc: payment.amountUsdc, billing: \"paid\" as const, receiptHash: payment.receiptHash };\n // The miner's JSON, either as the result itself or wrapped once by the node.\n const raw = (out.response.result ?? {}) as { id?: string; pending_id?: string; verdict?: string; reasons?: unknown; result?: { id?: string; pending_id?: string } };\n const id = raw.id ?? raw.result?.id;\n const pending = raw.pending_id ?? raw.result?.pending_id;\n if (!id && pending) {\n // The miner answered before its verdict was sealed (its deadline); the verdict is still being made.\n const v = await this.wait(pending, req.signal ? { signal: req.signal } : {});\n return { ...v, payment };\n }\n if (!id) {\n // Paid, but the miner abstained without a verdict (out of budget, upstream down): say what was paid.\n throw new SkeinError(\"TELEGRAPH_NO_VERDICT\", `the miner answered ${raw.verdict ?? \"without a verdict\"}, with no verdict id`, 502, raw, paid);\n }\n const v = await this.get(id);\n if (\"status\" in v && v.status === \"running\") {\n const sealed = await this.wait(id, req.signal ? { signal: req.signal } : {});\n return { ...sealed, payment };\n }\n return { ...(v as VerdictObject), payment };\n }\n}\n"],"mappings":"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","names":["value","v"]}
|
|
1
|
+
{"version":3,"sources":["../src/sse.ts","../src/index.ts"],"sourcesContent":["/** One parsed server-sent event. */\nexport interface RawEvent {\n event: string;\n data: string;\n id?: string;\n}\n\n/**\n * Parses a text/event-stream body into events (WHATWG rules: fields per line,\n * a blank line dispatches, \"data\" lines join with \\n, \":\" lines are comments).\n * Works on any fetch Response, in Node or the browser.\n */\nexport async function* parseSse(body: ReadableStream<Uint8Array>, signal?: AbortSignal): AsyncGenerator<RawEvent> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buf = \"\";\n let event = \"message\";\n let data: string[] = [];\n let id: string | undefined;\n const onAbort = () => void reader.cancel().catch(() => {});\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n try {\n for (;;) {\n const { value, done } = await reader.read();\n if (done) break;\n buf += decoder.decode(value, { stream: true });\n let nl: number;\n // A lone \"\\r\" at the end may be the first half of a \"\\r\\n\" split across chunks: wait for the next one.\n while ((nl = buf.search(/\\r\\n|\\r(?!$)|\\n/)) >= 0) {\n const line = buf.slice(0, nl);\n buf = buf.slice(nl + (buf.startsWith(\"\\r\\n\", nl) ? 2 : 1));\n if (line === \"\") {\n if (data.length) yield { event, data: data.join(\"\\n\"), ...(id !== undefined ? { id } : {}) };\n event = \"message\";\n data = [];\n continue;\n }\n if (line.startsWith(\":\")) continue;\n const colon = line.indexOf(\":\");\n const field = colon < 0 ? line : line.slice(0, colon);\n const value = colon < 0 ? \"\" : line.slice(colon + 1).replace(/^ /, \"\");\n if (field === \"event\") event = value;\n else if (field === \"data\") data.push(value);\n else if (field === \"id\") id = value;\n }\n }\n // A stream that ends mid-event drops it (WHATWG: an event is dispatched only by its blank line).\n } finally {\n signal?.removeEventListener(\"abort\", onAbort);\n // Stopping early (a terminal event, a break) must release the connection, not just the lock.\n await reader.cancel().catch(() => {});\n reader.releaseLock();\n }\n}\n","import { parseSse } from \"./sse\";\nimport type { Bom, Quote, Subject, TelegraphAsker, VerdictEvent, VerdictObject, VerifyReport } from \"./types\";\n\nexport * from \"./types\";\nexport { parseSse } from \"./sse\";\n\n/** The intent Skein serves on Telegraph (plan A; see miner/INTENT.md). */\nexport const SKEIN_INTENT = \"FRAUD_RISK_TOKEN_LISTING\";\n\nconst CHAIN_NAMES: Record<number, string> = { 1: \"ethereum\", 56: \"bsc\", 8453: \"base\", 42161: \"arbitrum\" };\n\n/**\n * How a verdict is paid for:\n * - apiKey: a Skein partner key against the HTTP API (free during the hackathon);\n * - telegraph: one paid Telegraph ask, routed to the Skein miner or pinned to it.\n * `client` is any Telegraph client, e.g. new TelegraphClient(...) from @skeinlabs/sdk/telegraph,\n * which enforces its own per-call price cap on the 402 challenge.\n */\nexport type Payer =\n | { kind: \"apiKey\"; key: string }\n | { kind: \"telegraph\"; client: TelegraphAsker; minerId?: string; intent?: string };\n\nexport interface SkeinOptions {\n /** e.g. https://api.skeinlabs.site (with or without /v1). */\n apiUrl: string;\n payer?: Payer;\n /** Refuse, before paying, any verdict whose quoted price is above this. */\n maxUsdcPerCall?: number;\n /** Retries for network errors, 429 and retryable 5xx. Default 2. */\n retries?: number;\n /** The most the SDK sleeps between retries of one call, in total; a longer Retry-After throws instead. Default 10 s. */\n maxRetryWaitMs?: number;\n /** Each HTTP request (submit, quote, get, verify) gives up after this. Default 15 s. */\n requestTimeoutMs?: number;\n /** How long verdict() waits for a result. Default 120 s. */\n timeoutMs?: number;\n fetch?: typeof fetch;\n}\n\nexport interface VerdictRequest {\n subject: Subject;\n /** \"dex-list@0.1.0\", or an id for its latest version. */\n policy?: string;\n /**\n * Optional evidence about the project. socialHandle buys the social-bot\n * check, repoUrl (github.com or gitlab.com) buys the code review.\n * `social` and `repo` are accepted as aliases.\n */\n context?: VerdictContextInput;\n /** Reuse to make a retried call return the original verdict. Generated when omitted. */\n idempotencyKey?: string;\n /** Called with each live event (API key path). */\n onEvent?: (e: VerdictEvent) => void;\n signal?: AbortSignal;\n /** A quote you already fetched for this request, so verdict() does not fetch another. */\n quote?: Quote;\n}\n\nexport interface VerdictContextInput {\n deployer?: string;\n socialHandle?: string;\n repoUrl?: string;\n treasuryAddresses?: string[];\n pool?: string;\n /** Alias of socialHandle. */\n social?: string;\n /** Alias of repoUrl. */\n repo?: string;\n}\n\n/** The API's field names: aliases mapped, empty values dropped. */\nexport function canonicalContext(c: VerdictContextInput | undefined): Record<string, unknown> | undefined {\n if (!c) return undefined;\n const { social, repo, ...rest } = c;\n const out: Record<string, unknown> = { ...rest };\n if (out.socialHandle === undefined && social) out.socialHandle = social;\n if (out.repoUrl === undefined && repo) out.repoUrl = repo;\n for (const [k, v] of Object.entries(out)) if (v === undefined || v === \"\" || (Array.isArray(v) && v.length === 0)) delete out[k];\n return Object.keys(out).length ? out : undefined;\n}\n\nexport type Payment =\n | { rail: \"apiKey\" }\n | { rail: \"telegraph\"; minerId: string; amountUsdc: number; receiptHash: string | null; signalHash: string | null };\n\nexport type VerdictResult = VerdictObject & { payment: Payment };\n\n/** Every API error, with the API's code (BUDGET_TOO_LOW, RATE_LIMITED, …) or an SDK code. */\nexport class SkeinError extends Error {\n constructor(\n readonly code: string,\n message: string,\n readonly status = 0,\n readonly details?: unknown,\n /**\n * Set when money moved (or may have) before the failure: a Telegraph ask\n * that was paid but produced no verdict. Count it against your caps.\n */\n readonly payment?: { amountUsdc: number; billing: \"paid\" | \"unknown\"; receiptHash?: string | null },\n ) {\n super(message);\n this.name = \"SkeinError\";\n }\n}\n\n/** The quoted price is above maxUsdcPerCall; nothing was paid. */\nexport class SpendCapError extends SkeinError {\n constructor(\n readonly priceUsdc: number,\n readonly capUsdc: number,\n ) {\n super(\"SPEND_CAP\", `quoted ${priceUsdc} USDC is above the cap of ${capUsdc} USDC; nothing was paid`);\n this.name = \"SpendCapError\";\n }\n}\n\n/** Refusals that will not change on retry. */\nconst FINAL = new Set([\"UPSTREAM_UNAVAILABLE\", \"DAILY_CAP_REACHED\", \"MARGIN_GUARD\", \"SELF_ROUTING\", \"BUDGET_TOO_LOW\"]);\nconst sleep = (ms: number, signal?: AbortSignal) =>\n new Promise<void>((resolve, reject) => {\n const t = setTimeout(resolve, ms);\n signal?.addEventListener(\"abort\", () => (clearTimeout(t), reject(signal.reason)), { once: true });\n });\n\nexport class Skein {\n private readonly base: string;\n private readonly fetch: typeof fetch;\n private readonly retries: number;\n private readonly timeoutMs: number;\n\n constructor(private readonly opts: SkeinOptions) {\n this.base = opts.apiUrl.replace(/\\/$/, \"\").replace(/\\/v1$/, \"\");\n this.fetch = opts.fetch ?? ((...a) => globalThis.fetch(...a));\n this.retries = opts.retries ?? 2;\n this.timeoutMs = opts.timeoutMs ?? 120_000;\n this.maxRetryWaitMs = opts.maxRetryWaitMs ?? 10_000;\n this.requestTimeoutMs = opts.requestTimeoutMs ?? 15_000;\n }\n\n private readonly maxRetryWaitMs: number;\n private readonly requestTimeoutMs: number;\n\n /** One HTTP request with its own deadline, still cancellable by the caller's signal. */\n private async request(url: string, init: RequestInit): Promise<{ res: Response; json: unknown }> {\n const ctl = new AbortController();\n const timer = setTimeout(() => ctl.abort(new DOMException(\"request timed out\", \"TimeoutError\")), this.requestTimeoutMs);\n const onAbort = () => ctl.abort(init.signal?.reason);\n init.signal?.addEventListener(\"abort\", onAbort, { once: true });\n try {\n const res = await this.fetch(url, { ...init, signal: ctl.signal });\n const json = await res.json().catch(() => null);\n return { res, json };\n } finally {\n clearTimeout(timer);\n init.signal?.removeEventListener(\"abort\", onAbort);\n }\n }\n\n /**\n * A raw call with typed errors and retries. POSTs are retried only with an\n * idempotency key. Retries sleep at most maxRetryWaitMs in total: a\n * Retry-After past that (a daily cap until midnight) throws at once.\n */\n private async call<T>(path: string, init: RequestInit = {}, retryable = (init.method ?? \"GET\") === \"GET\"): Promise<{ status: number; body: T }> {\n let waited = 0;\n for (let attempt = 0; ; attempt++) {\n let res: Response;\n let json: (T & { error?: { code: string; message: string; details?: unknown } }) | null;\n try {\n ({ res, json } = (await this.request(`${this.base}${path}`, init)) as { res: Response; json: typeof json });\n } catch (e) {\n if (init.signal?.aborted) throw e;\n const backoff = 500 * 2 ** attempt;\n if (retryable && attempt < this.retries && waited + backoff <= this.maxRetryWaitMs) {\n waited += backoff;\n await sleep(backoff, init.signal ?? undefined);\n continue;\n }\n const timedOut = (e as Error).name === \"TimeoutError\";\n throw new SkeinError(timedOut ? \"TIMEOUT\" : \"NETWORK\", timedOut ? `no answer from Skein in ${this.requestTimeoutMs} ms` : `could not reach Skein: ${(e as Error).message}`);\n }\n if (res.ok) return { status: res.status, body: json as T };\n const err = json?.error ?? { code: `HTTP_${res.status}`, message: res.statusText || `HTTP ${res.status}` };\n const after = Number(res.headers.get(\"retry-after\"));\n const wait = Number.isFinite(after) && after > 0 ? after * 1000 : 500 * 2 ** attempt;\n const again = retryable && attempt < this.retries && (res.status === 429 || (res.status >= 500 && !FINAL.has(err.code))) && waited + wait <= this.maxRetryWaitMs;\n if (!again) throw new SkeinError(err.code, err.message, res.status, err.details);\n waited += wait;\n await sleep(wait, init.signal ?? undefined);\n }\n }\n\n /** What a verdict would buy and cost, without buying. Free. */\n async quote(req: { subject: Subject; policy?: string }): Promise<Quote> {\n const q = new URLSearchParams({ chain: String(req.subject.chainId), token: req.subject.token });\n if (req.policy) q.set(\"policy\", req.policy);\n return (await this.call<Quote>(`/v1/quote?${q}`)).body;\n }\n\n /** A stored verdict, or { status: \"running\" } while it is being made. */\n async get(id: string): Promise<VerdictObject | { id: string; status: \"running\" }> {\n return (await this.call<VerdictObject | { id: string; status: \"running\" }>(`/v1/verdicts/${encodeURIComponent(id)}`)).body;\n }\n\n /** The bill of materials: every paid input and its receipt. */\n async bom(id: string): Promise<Bom> {\n return (await this.call<Bom>(`/v1/verdicts/${encodeURIComponent(id)}/bom`)).body;\n }\n\n /** Recompute a verdict from its raw paid answers. */\n async verify(id: string): Promise<VerifyReport> {\n return (\n await this.call<VerifyReport>(\"/v1/verify\", { method: \"POST\", headers: { \"content-type\": \"application/json\" }, body: JSON.stringify({ id }) }, true)\n ).body;\n }\n\n /** The live events of a verdict, replayed from the start; ends after done, refused or error. */\n async *stream(id: string, opts: { signal?: AbortSignal } = {}): AsyncGenerator<VerdictEvent> {\n const res = await this.fetch(`${this.base}/v1/verdicts/${encodeURIComponent(id)}/events`, {\n headers: { accept: \"text/event-stream\" },\n ...(opts.signal ? { signal: opts.signal } : {}),\n });\n if (!res.ok || !res.body) throw new SkeinError(`HTTP_${res.status}`, `event stream failed: HTTP ${res.status}`, res.status);\n for await (const raw of parseSse(res.body, opts.signal)) {\n let data: unknown;\n try {\n data = JSON.parse(raw.data);\n } catch {\n continue;\n }\n const e = { type: raw.event, data } as VerdictEvent;\n yield e;\n if (e.type === \"done\" || e.type === \"refused\" || e.type === \"error\") return;\n }\n }\n\n /**\n * Buys one verdict and returns it once it is sealed. With maxUsdcPerCall\n * set, the price is quoted first and the call refused before any payment.\n */\n async verdict(req: VerdictRequest): Promise<VerdictResult> {\n const payer = this.opts.payer;\n if (!payer) throw new SkeinError(\"NO_PAYER\", \"verdict() needs a payer: { kind: 'apiKey', key } or { kind: 'telegraph', client }\");\n if (this.opts.maxUsdcPerCall !== undefined) {\n const q = req.quote ?? (await this.quote({ subject: req.subject, ...(req.policy ? { policy: req.policy } : {}) }));\n if (!q.ok && q.refusal) throw new SkeinError(q.refusal.code, q.refusal.detail, q.refusal.code === \"BUDGET_TOO_LOW\" ? 422 : 503, q.refusal);\n if (q.priceUsdc > this.opts.maxUsdcPerCall) throw new SpendCapError(q.priceUsdc, this.opts.maxUsdcPerCall);\n }\n return payer.kind === \"apiKey\" ? this.viaApi(req) : this.viaTelegraph(payer, req);\n }\n\n /**\n * Starts a verdict on the partner-key rail and returns at once: the id while\n * it runs, or the verdict itself when it is cached or replayed. Pair with\n * wait(id). Spend-cap checks are the caller's (verdict() does them).\n */\n async submit(req: VerdictRequest): Promise<{ id: string; status: \"running\" } | VerdictResult> {\n const payer = this.opts.payer;\n if (payer?.kind !== \"apiKey\") throw new SkeinError(\"NO_PAYER\", \"submit() needs an apiKey payer\");\n const { status, body } = await this.call<VerdictObject | { id: string; status: \"running\" }>(\n \"/v1/verdicts\",\n {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", authorization: `Bearer ${payer.key}`, \"idempotency-key\": req.idempotencyKey ?? crypto.randomUUID() },\n body: JSON.stringify({\n subject: req.subject,\n ...(req.policy ? { policy: req.policy } : {}),\n ...(canonicalContext(req.context) ? { context: canonicalContext(req.context) } : {}),\n ...(this.opts.maxUsdcPerCall !== undefined ? { budgetUsdcMax: this.opts.maxUsdcPerCall } : {}),\n mode: \"async\",\n }),\n ...(req.signal ? { signal: req.signal } : {}),\n },\n true,\n );\n return status === 202 ? (body as { id: string; status: \"running\" }) : { ...(body as VerdictObject), payment: { rail: \"apiKey\" } };\n }\n\n /**\n * Waits for a submitted verdict: follows its event stream (falling back to\n * polling if the stream drops) and throws a SkeinError if it is refused.\n */\n async wait(id: string, opts: { onEvent?: (e: VerdictEvent) => void; signal?: AbortSignal; timeoutMs?: number } = {}): Promise<VerdictResult> {\n const deadline = Date.now() + (opts.timeoutMs ?? this.timeoutMs);\n const timeout = AbortSignal.timeout(Math.max(1, deadline - Date.now()));\n const signal = opts.signal ? AbortSignal.any([opts.signal, timeout]) : timeout;\n try {\n for await (const e of this.stream(id, { signal })) {\n opts.onEvent?.(e);\n if (e.type === \"refused\") throw new SkeinError(e.data.code, e.data.detail, e.data.code === \"BUDGET_TOO_LOW\" ? 422 : 503, e.data);\n if (e.type === \"error\") throw new SkeinError(\"VERDICT_FAILED\", e.data.message, 503);\n }\n } catch (e) {\n if (e instanceof SkeinError && !e.code.startsWith(\"HTTP_\")) throw e;\n if (opts.signal?.aborted) throw e;\n // The stream dropped or timed out: fall back to polling until the deadline.\n }\n for (;;) {\n const v = await this.get(id);\n if (!(\"status\" in v && v.status === \"running\")) return { ...(v as VerdictObject), payment: { rail: \"apiKey\" } };\n if (Date.now() >= deadline) throw new SkeinError(\"TIMEOUT\", `verdict ${id} is still running; call wait(id) again`, 504, { id });\n await sleep(Math.min(1000, Math.max(0, deadline - Date.now())), opts.signal);\n }\n }\n\n private async viaApi(req: VerdictRequest): Promise<VerdictResult> {\n const started = await this.submit(req);\n if (!(\"status\" in started && started.status === \"running\")) return started as VerdictResult;\n return this.wait(started.id, { ...(req.onEvent ? { onEvent: req.onEvent } : {}), ...(req.signal ? { signal: req.signal } : {}) });\n }\n\n private async viaTelegraph(payer: Extract<Payer, { kind: \"telegraph\" }>, req: VerdictRequest): Promise<VerdictResult> {\n const params = {\n token: req.subject.token,\n chain: CHAIN_NAMES[req.subject.chainId] ?? String(req.subject.chainId),\n subject: req.subject,\n ...(req.policy ? { policy: req.policy } : {}),\n ...(canonicalContext(req.context) ? { context: canonicalContext(req.context) } : {}),\n };\n const out = await payer.client.ask({ intent: payer.intent ?? SKEIN_INTENT, params }, { ...(payer.minerId ? { minerId: payer.minerId } : {}), timeoutMs: this.timeoutMs });\n if (!out.ok) {\n const paidUusdc = (out as { paidUusdc?: number }).paidUusdc ?? 0;\n throw new SkeinError(\n `TELEGRAPH_${out.kind.toUpperCase()}`,\n out.error,\n out.httpStatus ?? 0,\n undefined,\n paidUusdc > 0 ? { amountUsdc: paidUusdc / 1e6, billing: \"unknown\" } : undefined,\n );\n }\n const payment: Payment = {\n rail: \"telegraph\",\n minerId: out.response.miner_id,\n amountUsdc: out.amountUusdc / 1e6,\n receiptHash: out.receipt?.receipt_hash ?? null,\n signalHash: out.response.signal_hash ?? null,\n };\n const paid = { amountUsdc: payment.amountUsdc, billing: \"paid\" as const, receiptHash: payment.receiptHash };\n // The miner's JSON, either as the result itself or wrapped once by the node.\n const raw = (out.response.result ?? {}) as { id?: string; pending_id?: string; verdict?: string; reasons?: unknown; result?: { id?: string; pending_id?: string } };\n const id = raw.id ?? raw.result?.id;\n const pending = raw.pending_id ?? raw.result?.pending_id;\n if (!id && pending) {\n // The miner answered before its verdict was sealed (its deadline); the verdict is still being made.\n const v = await this.wait(pending, req.signal ? { signal: req.signal } : {});\n return { ...v, payment };\n }\n if (!id) {\n // Paid, but the miner abstained without a verdict (out of budget, upstream down): say what was paid.\n throw new SkeinError(\"TELEGRAPH_NO_VERDICT\", `the miner answered ${raw.verdict ?? \"without a verdict\"}, with no verdict id`, 502, raw, paid);\n }\n const v = await this.get(id);\n if (\"status\" in v && v.status === \"running\") {\n const sealed = await this.wait(id, req.signal ? { signal: req.signal } : {});\n return { ...sealed, payment };\n }\n return { ...(v as VerdictObject), payment };\n }\n}\n"],"mappings":";AAYA,gBAAuB,SAAS,MAAkC,QAAgD;AAChH,QAAM,SAAS,KAAK,UAAU;AAC9B,QAAM,UAAU,IAAI,YAAY;AAChC,MAAI,MAAM;AACV,MAAI,QAAQ;AACZ,MAAI,OAAiB,CAAC;AACtB,MAAI;AACJ,QAAM,UAAU,MAAM,KAAK,OAAO,OAAO,EAAE,MAAM,MAAM;AAAA,EAAC,CAAC;AACzD,UAAQ,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AACzD,MAAI;AACF,eAAS;AACP,YAAM,EAAE,OAAO,KAAK,IAAI,MAAM,OAAO,KAAK;AAC1C,UAAI,KAAM;AACV,aAAO,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAC7C,UAAI;AAEJ,cAAQ,KAAK,IAAI,OAAO,iBAAiB,MAAM,GAAG;AAChD,cAAM,OAAO,IAAI,MAAM,GAAG,EAAE;AAC5B,cAAM,IAAI,MAAM,MAAM,IAAI,WAAW,QAAQ,EAAE,IAAI,IAAI,EAAE;AACzD,YAAI,SAAS,IAAI;AACf,cAAI,KAAK,OAAQ,OAAM,EAAE,OAAO,MAAM,KAAK,KAAK,IAAI,GAAG,GAAI,OAAO,SAAY,EAAE,GAAG,IAAI,CAAC,EAAG;AAC3F,kBAAQ;AACR,iBAAO,CAAC;AACR;AAAA,QACF;AACA,YAAI,KAAK,WAAW,GAAG,EAAG;AAC1B,cAAM,QAAQ,KAAK,QAAQ,GAAG;AAC9B,cAAM,QAAQ,QAAQ,IAAI,OAAO,KAAK,MAAM,GAAG,KAAK;AACpD,cAAMA,SAAQ,QAAQ,IAAI,KAAK,KAAK,MAAM,QAAQ,CAAC,EAAE,QAAQ,MAAM,EAAE;AACrE,YAAI,UAAU,QAAS,SAAQA;AAAA,iBACtB,UAAU,OAAQ,MAAK,KAAKA,MAAK;AAAA,iBACjC,UAAU,KAAM,MAAKA;AAAA,MAChC;AAAA,IACF;AAAA,EAEF,UAAE;AACA,YAAQ,oBAAoB,SAAS,OAAO;AAE5C,UAAM,OAAO,OAAO,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AACpC,WAAO,YAAY;AAAA,EACrB;AACF;;;AC9CO,IAAM,eAAe;AAE5B,IAAM,cAAsC,EAAE,GAAG,YAAY,IAAI,OAAO,MAAM,QAAQ,OAAO,WAAW;AA8DjG,SAAS,iBAAiB,GAAyE;AACxG,MAAI,CAAC,EAAG,QAAO;AACf,QAAM,EAAE,QAAQ,MAAM,GAAG,KAAK,IAAI;AAClC,QAAM,MAA+B,EAAE,GAAG,KAAK;AAC/C,MAAI,IAAI,iBAAiB,UAAa,OAAQ,KAAI,eAAe;AACjE,MAAI,IAAI,YAAY,UAAa,KAAM,KAAI,UAAU;AACrD,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,GAAG,EAAG,KAAI,MAAM,UAAa,MAAM,MAAO,MAAM,QAAQ,CAAC,KAAK,EAAE,WAAW,EAAI,QAAO,IAAI,CAAC;AAC/H,SAAO,OAAO,KAAK,GAAG,EAAE,SAAS,MAAM;AACzC;AASO,IAAM,aAAN,cAAyB,MAAM;AAAA,EACpC,YACW,MACT,SACS,SAAS,GACT,SAKA,SACT;AACA,UAAM,OAAO;AAVJ;AAEA;AACA;AAKA;AAGT,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAM,gBAAN,cAA4B,WAAW;AAAA,EAC5C,YACW,WACA,SACT;AACA,UAAM,aAAa,UAAU,SAAS,6BAA6B,OAAO,yBAAyB;AAH1F;AACA;AAGT,SAAK,OAAO;AAAA,EACd;AACF;AAGA,IAAM,QAAQ,oBAAI,IAAI,CAAC,wBAAwB,qBAAqB,gBAAgB,gBAAgB,gBAAgB,CAAC;AACrH,IAAM,QAAQ,CAAC,IAAY,WACzB,IAAI,QAAc,CAAC,SAAS,WAAW;AACrC,QAAM,IAAI,WAAW,SAAS,EAAE;AAChC,UAAQ,iBAAiB,SAAS,OAAO,aAAa,CAAC,GAAG,OAAO,OAAO,MAAM,IAAI,EAAE,MAAM,KAAK,CAAC;AAClG,CAAC;AAEI,IAAM,QAAN,MAAY;AAAA,EAMjB,YAA6B,MAAoB;AAApB;AAC3B,SAAK,OAAO,KAAK,OAAO,QAAQ,OAAO,EAAE,EAAE,QAAQ,SAAS,EAAE;AAC9D,SAAK,QAAQ,KAAK,UAAU,IAAI,MAAM,WAAW,MAAM,GAAG,CAAC;AAC3D,SAAK,UAAU,KAAK,WAAW;AAC/B,SAAK,YAAY,KAAK,aAAa;AACnC,SAAK,iBAAiB,KAAK,kBAAkB;AAC7C,SAAK,mBAAmB,KAAK,oBAAoB;AAAA,EACnD;AAAA,EAZiB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAWA;AAAA,EACA;AAAA;AAAA,EAGjB,MAAc,QAAQ,KAAa,MAA8D;AAC/F,UAAM,MAAM,IAAI,gBAAgB;AAChC,UAAM,QAAQ,WAAW,MAAM,IAAI,MAAM,IAAI,aAAa,qBAAqB,cAAc,CAAC,GAAG,KAAK,gBAAgB;AACtH,UAAM,UAAU,MAAM,IAAI,MAAM,KAAK,QAAQ,MAAM;AACnD,SAAK,QAAQ,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AAC9D,QAAI;AACF,YAAM,MAAM,MAAM,KAAK,MAAM,KAAK,EAAE,GAAG,MAAM,QAAQ,IAAI,OAAO,CAAC;AACjE,YAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,IAAI;AAC9C,aAAO,EAAE,KAAK,KAAK;AAAA,IACrB,UAAE;AACA,mBAAa,KAAK;AAClB,WAAK,QAAQ,oBAAoB,SAAS,OAAO;AAAA,IACnD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,KAAQ,MAAc,OAAoB,CAAC,GAAG,aAAa,KAAK,UAAU,WAAW,OAA6C;AAC9I,QAAI,SAAS;AACb,aAAS,UAAU,KAAK,WAAW;AACjC,UAAI;AACJ,UAAI;AACJ,UAAI;AACF,SAAC,EAAE,KAAK,KAAK,IAAK,MAAM,KAAK,QAAQ,GAAG,KAAK,IAAI,GAAG,IAAI,IAAI,IAAI;AAAA,MAClE,SAAS,GAAG;AACV,YAAI,KAAK,QAAQ,QAAS,OAAM;AAChC,cAAM,UAAU,MAAM,KAAK;AAC3B,YAAI,aAAa,UAAU,KAAK,WAAW,SAAS,WAAW,KAAK,gBAAgB;AAClF,oBAAU;AACV,gBAAM,MAAM,SAAS,KAAK,UAAU,MAAS;AAC7C;AAAA,QACF;AACA,cAAM,WAAY,EAAY,SAAS;AACvC,cAAM,IAAI,WAAW,WAAW,YAAY,WAAW,WAAW,2BAA2B,KAAK,gBAAgB,QAAQ,0BAA2B,EAAY,OAAO,EAAE;AAAA,MAC5K;AACA,UAAI,IAAI,GAAI,QAAO,EAAE,QAAQ,IAAI,QAAQ,MAAM,KAAU;AACzD,YAAM,MAAM,MAAM,SAAS,EAAE,MAAM,QAAQ,IAAI,MAAM,IAAI,SAAS,IAAI,cAAc,QAAQ,IAAI,MAAM,GAAG;AACzG,YAAM,QAAQ,OAAO,IAAI,QAAQ,IAAI,aAAa,CAAC;AACnD,YAAM,OAAO,OAAO,SAAS,KAAK,KAAK,QAAQ,IAAI,QAAQ,MAAO,MAAM,KAAK;AAC7E,YAAM,QAAQ,aAAa,UAAU,KAAK,YAAY,IAAI,WAAW,OAAQ,IAAI,UAAU,OAAO,CAAC,MAAM,IAAI,IAAI,IAAI,MAAO,SAAS,QAAQ,KAAK;AAClJ,UAAI,CAAC,MAAO,OAAM,IAAI,WAAW,IAAI,MAAM,IAAI,SAAS,IAAI,QAAQ,IAAI,OAAO;AAC/E,gBAAU;AACV,YAAM,MAAM,MAAM,KAAK,UAAU,MAAS;AAAA,IAC5C;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,MAAM,KAA4D;AACtE,UAAM,IAAI,IAAI,gBAAgB,EAAE,OAAO,OAAO,IAAI,QAAQ,OAAO,GAAG,OAAO,IAAI,QAAQ,MAAM,CAAC;AAC9F,QAAI,IAAI,OAAQ,GAAE,IAAI,UAAU,IAAI,MAAM;AAC1C,YAAQ,MAAM,KAAK,KAAY,aAAa,CAAC,EAAE,GAAG;AAAA,EACpD;AAAA;AAAA,EAGA,MAAM,IAAI,IAAwE;AAChF,YAAQ,MAAM,KAAK,KAAwD,gBAAgB,mBAAmB,EAAE,CAAC,EAAE,GAAG;AAAA,EACxH;AAAA;AAAA,EAGA,MAAM,IAAI,IAA0B;AAClC,YAAQ,MAAM,KAAK,KAAU,gBAAgB,mBAAmB,EAAE,CAAC,MAAM,GAAG;AAAA,EAC9E;AAAA;AAAA,EAGA,MAAM,OAAO,IAAmC;AAC9C,YACE,MAAM,KAAK,KAAmB,cAAc,EAAE,QAAQ,QAAQ,SAAS,EAAE,gBAAgB,mBAAmB,GAAG,MAAM,KAAK,UAAU,EAAE,GAAG,CAAC,EAAE,GAAG,IAAI,GACnJ;AAAA,EACJ;AAAA;AAAA,EAGA,OAAO,OAAO,IAAY,OAAiC,CAAC,GAAiC;AAC3F,UAAM,MAAM,MAAM,KAAK,MAAM,GAAG,KAAK,IAAI,gBAAgB,mBAAmB,EAAE,CAAC,WAAW;AAAA,MACxF,SAAS,EAAE,QAAQ,oBAAoB;AAAA,MACvC,GAAI,KAAK,SAAS,EAAE,QAAQ,KAAK,OAAO,IAAI,CAAC;AAAA,IAC/C,CAAC;AACD,QAAI,CAAC,IAAI,MAAM,CAAC,IAAI,KAAM,OAAM,IAAI,WAAW,QAAQ,IAAI,MAAM,IAAI,6BAA6B,IAAI,MAAM,IAAI,IAAI,MAAM;AAC1H,qBAAiB,OAAO,SAAS,IAAI,MAAM,KAAK,MAAM,GAAG;AACvD,UAAI;AACJ,UAAI;AACF,eAAO,KAAK,MAAM,IAAI,IAAI;AAAA,MAC5B,QAAQ;AACN;AAAA,MACF;AACA,YAAM,IAAI,EAAE,MAAM,IAAI,OAAO,KAAK;AAClC,YAAM;AACN,UAAI,EAAE,SAAS,UAAU,EAAE,SAAS,aAAa,EAAE,SAAS,QAAS;AAAA,IACvE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,QAAQ,KAA6C;AACzD,UAAM,QAAQ,KAAK,KAAK;AACxB,QAAI,CAAC,MAAO,OAAM,IAAI,WAAW,YAAY,mFAAmF;AAChI,QAAI,KAAK,KAAK,mBAAmB,QAAW;AAC1C,YAAM,IAAI,IAAI,SAAU,MAAM,KAAK,MAAM,EAAE,SAAS,IAAI,SAAS,GAAI,IAAI,SAAS,EAAE,QAAQ,IAAI,OAAO,IAAI,CAAC,EAAG,CAAC;AAChH,UAAI,CAAC,EAAE,MAAM,EAAE,QAAS,OAAM,IAAI,WAAW,EAAE,QAAQ,MAAM,EAAE,QAAQ,QAAQ,EAAE,QAAQ,SAAS,mBAAmB,MAAM,KAAK,EAAE,OAAO;AACzI,UAAI,EAAE,YAAY,KAAK,KAAK,eAAgB,OAAM,IAAI,cAAc,EAAE,WAAW,KAAK,KAAK,cAAc;AAAA,IAC3G;AACA,WAAO,MAAM,SAAS,WAAW,KAAK,OAAO,GAAG,IAAI,KAAK,aAAa,OAAO,GAAG;AAAA,EAClF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,OAAO,KAAiF;AAC5F,UAAM,QAAQ,KAAK,KAAK;AACxB,QAAI,OAAO,SAAS,SAAU,OAAM,IAAI,WAAW,YAAY,gCAAgC;AAC/F,UAAM,EAAE,QAAQ,KAAK,IAAI,MAAM,KAAK;AAAA,MAClC;AAAA,MACA;AAAA,QACE,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,oBAAoB,eAAe,UAAU,MAAM,GAAG,IAAI,mBAAmB,IAAI,kBAAkB,OAAO,WAAW,EAAE;AAAA,QAClJ,MAAM,KAAK,UAAU;AAAA,UACnB,SAAS,IAAI;AAAA,UACb,GAAI,IAAI,SAAS,EAAE,QAAQ,IAAI,OAAO,IAAI,CAAC;AAAA,UAC3C,GAAI,iBAAiB,IAAI,OAAO,IAAI,EAAE,SAAS,iBAAiB,IAAI,OAAO,EAAE,IAAI,CAAC;AAAA,UAClF,GAAI,KAAK,KAAK,mBAAmB,SAAY,EAAE,eAAe,KAAK,KAAK,eAAe,IAAI,CAAC;AAAA,UAC5F,MAAM;AAAA,QACR,CAAC;AAAA,QACD,GAAI,IAAI,SAAS,EAAE,QAAQ,IAAI,OAAO,IAAI,CAAC;AAAA,MAC7C;AAAA,MACA;AAAA,IACF;AACA,WAAO,WAAW,MAAO,OAA6C,EAAE,GAAI,MAAwB,SAAS,EAAE,MAAM,SAAS,EAAE;AAAA,EAClI;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,KAAK,IAAY,OAA0F,CAAC,GAA2B;AAC3I,UAAM,WAAW,KAAK,IAAI,KAAK,KAAK,aAAa,KAAK;AACtD,UAAM,UAAU,YAAY,QAAQ,KAAK,IAAI,GAAG,WAAW,KAAK,IAAI,CAAC,CAAC;AACtE,UAAM,SAAS,KAAK,SAAS,YAAY,IAAI,CAAC,KAAK,QAAQ,OAAO,CAAC,IAAI;AACvE,QAAI;AACF,uBAAiB,KAAK,KAAK,OAAO,IAAI,EAAE,OAAO,CAAC,GAAG;AACjD,aAAK,UAAU,CAAC;AAChB,YAAI,EAAE,SAAS,UAAW,OAAM,IAAI,WAAW,EAAE,KAAK,MAAM,EAAE,KAAK,QAAQ,EAAE,KAAK,SAAS,mBAAmB,MAAM,KAAK,EAAE,IAAI;AAC/H,YAAI,EAAE,SAAS,QAAS,OAAM,IAAI,WAAW,kBAAkB,EAAE,KAAK,SAAS,GAAG;AAAA,MACpF;AAAA,IACF,SAAS,GAAG;AACV,UAAI,aAAa,cAAc,CAAC,EAAE,KAAK,WAAW,OAAO,EAAG,OAAM;AAClE,UAAI,KAAK,QAAQ,QAAS,OAAM;AAAA,IAElC;AACA,eAAS;AACP,YAAM,IAAI,MAAM,KAAK,IAAI,EAAE;AAC3B,UAAI,EAAE,YAAY,KAAK,EAAE,WAAW,WAAY,QAAO,EAAE,GAAI,GAAqB,SAAS,EAAE,MAAM,SAAS,EAAE;AAC9G,UAAI,KAAK,IAAI,KAAK,SAAU,OAAM,IAAI,WAAW,WAAW,WAAW,EAAE,0CAA0C,KAAK,EAAE,GAAG,CAAC;AAC9H,YAAM,MAAM,KAAK,IAAI,KAAM,KAAK,IAAI,GAAG,WAAW,KAAK,IAAI,CAAC,CAAC,GAAG,KAAK,MAAM;AAAA,IAC7E;AAAA,EACF;AAAA,EAEA,MAAc,OAAO,KAA6C;AAChE,UAAM,UAAU,MAAM,KAAK,OAAO,GAAG;AACrC,QAAI,EAAE,YAAY,WAAW,QAAQ,WAAW,WAAY,QAAO;AACnE,WAAO,KAAK,KAAK,QAAQ,IAAI,EAAE,GAAI,IAAI,UAAU,EAAE,SAAS,IAAI,QAAQ,IAAI,CAAC,GAAI,GAAI,IAAI,SAAS,EAAE,QAAQ,IAAI,OAAO,IAAI,CAAC,EAAG,CAAC;AAAA,EAClI;AAAA,EAEA,MAAc,aAAa,OAA8C,KAA6C;AACpH,UAAM,SAAS;AAAA,MACb,OAAO,IAAI,QAAQ;AAAA,MACnB,OAAO,YAAY,IAAI,QAAQ,OAAO,KAAK,OAAO,IAAI,QAAQ,OAAO;AAAA,MACrE,SAAS,IAAI;AAAA,MACb,GAAI,IAAI,SAAS,EAAE,QAAQ,IAAI,OAAO,IAAI,CAAC;AAAA,MAC3C,GAAI,iBAAiB,IAAI,OAAO,IAAI,EAAE,SAAS,iBAAiB,IAAI,OAAO,EAAE,IAAI,CAAC;AAAA,IACpF;AACA,UAAM,MAAM,MAAM,MAAM,OAAO,IAAI,EAAE,QAAQ,MAAM,UAAU,cAAc,OAAO,GAAG,EAAE,GAAI,MAAM,UAAU,EAAE,SAAS,MAAM,QAAQ,IAAI,CAAC,GAAI,WAAW,KAAK,UAAU,CAAC;AACxK,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,YAAa,IAA+B,aAAa;AAC/D,YAAM,IAAI;AAAA,QACR,aAAa,IAAI,KAAK,YAAY,CAAC;AAAA,QACnC,IAAI;AAAA,QACJ,IAAI,cAAc;AAAA,QAClB;AAAA,QACA,YAAY,IAAI,EAAE,YAAY,YAAY,KAAK,SAAS,UAAU,IAAI;AAAA,MACxE;AAAA,IACF;AACA,UAAM,UAAmB;AAAA,MACvB,MAAM;AAAA,MACN,SAAS,IAAI,SAAS;AAAA,MACtB,YAAY,IAAI,cAAc;AAAA,MAC9B,aAAa,IAAI,SAAS,gBAAgB;AAAA,MAC1C,YAAY,IAAI,SAAS,eAAe;AAAA,IAC1C;AACA,UAAM,OAAO,EAAE,YAAY,QAAQ,YAAY,SAAS,QAAiB,aAAa,QAAQ,YAAY;AAE1G,UAAM,MAAO,IAAI,SAAS,UAAU,CAAC;AACrC,UAAM,KAAK,IAAI,MAAM,IAAI,QAAQ;AACjC,UAAM,UAAU,IAAI,cAAc,IAAI,QAAQ;AAC9C,QAAI,CAAC,MAAM,SAAS;AAElB,YAAMC,KAAI,MAAM,KAAK,KAAK,SAAS,IAAI,SAAS,EAAE,QAAQ,IAAI,OAAO,IAAI,CAAC,CAAC;AAC3E,aAAO,EAAE,GAAGA,IAAG,QAAQ;AAAA,IACzB;AACA,QAAI,CAAC,IAAI;AAEP,YAAM,IAAI,WAAW,wBAAwB,sBAAsB,IAAI,WAAW,mBAAmB,wBAAwB,KAAK,KAAK,IAAI;AAAA,IAC7I;AACA,UAAM,IAAI,MAAM,KAAK,IAAI,EAAE;AAC3B,QAAI,YAAY,KAAK,EAAE,WAAW,WAAW;AAC3C,YAAM,SAAS,MAAM,KAAK,KAAK,IAAI,IAAI,SAAS,EAAE,QAAQ,IAAI,OAAO,IAAI,CAAC,CAAC;AAC3E,aAAO,EAAE,GAAG,QAAQ,QAAQ;AAAA,IAC9B;AACA,WAAO,EAAE,GAAI,GAAqB,QAAQ;AAAA,EAC5C;AACF;","names":["value","v"]}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
type Verdict = "APPROVE" | "REJECT" | "ESCALATE" | "ABSTAIN";
|
|
2
|
+
type CheckStatus = "PASS" | "WARN" | "FAIL" | "UNKNOWN" | "UNAVAILABLE" | "ERROR";
|
|
3
|
+
interface Subject {
|
|
4
|
+
chainId: number;
|
|
5
|
+
token: string;
|
|
6
|
+
}
|
|
7
|
+
interface Finding {
|
|
8
|
+
check: string;
|
|
9
|
+
status: CheckStatus;
|
|
10
|
+
severity: number;
|
|
11
|
+
metric?: string;
|
|
12
|
+
value?: number;
|
|
13
|
+
unit?: string;
|
|
14
|
+
confidence: number;
|
|
15
|
+
sourceGroup: string;
|
|
16
|
+
evidence?: {
|
|
17
|
+
receiptHash?: string;
|
|
18
|
+
signalHash?: string;
|
|
19
|
+
minerId?: string;
|
|
20
|
+
};
|
|
21
|
+
notes: string[];
|
|
22
|
+
}
|
|
23
|
+
/** Skein's signature over a verdict (EIP-191); check it with @skeinlabs/sdk/attest. */
|
|
24
|
+
interface Attestation {
|
|
25
|
+
scheme: "eip191";
|
|
26
|
+
/** Skein's attester address, published at /v1/status. */
|
|
27
|
+
signer: string;
|
|
28
|
+
/** The exact signed text: the verdict's id, subject, outcome, policy, hashes and cost. */
|
|
29
|
+
message: string;
|
|
30
|
+
signature: string;
|
|
31
|
+
}
|
|
32
|
+
/** The verdict object (build spec, section 6). */
|
|
33
|
+
interface VerdictObject {
|
|
34
|
+
id: string;
|
|
35
|
+
verdict: Verdict;
|
|
36
|
+
verdictCode: number;
|
|
37
|
+
riskBps: number;
|
|
38
|
+
confidenceBps: number;
|
|
39
|
+
coverage: number;
|
|
40
|
+
summary: string;
|
|
41
|
+
reasons: {
|
|
42
|
+
code: string;
|
|
43
|
+
check?: string;
|
|
44
|
+
detail: string;
|
|
45
|
+
}[];
|
|
46
|
+
openRisks: string[];
|
|
47
|
+
conflicts: string[];
|
|
48
|
+
subject: Subject;
|
|
49
|
+
findings: Finding[];
|
|
50
|
+
cost: {
|
|
51
|
+
upstreamUsdc: number;
|
|
52
|
+
priceUsdc: number;
|
|
53
|
+
currency: string;
|
|
54
|
+
};
|
|
55
|
+
bom: {
|
|
56
|
+
root: string;
|
|
57
|
+
items: number;
|
|
58
|
+
};
|
|
59
|
+
policy: {
|
|
60
|
+
id: string;
|
|
61
|
+
version: string;
|
|
62
|
+
};
|
|
63
|
+
engineVersion: string;
|
|
64
|
+
verdictHash: string;
|
|
65
|
+
channel: string;
|
|
66
|
+
network: string;
|
|
67
|
+
createdAt: string;
|
|
68
|
+
durationMs: number;
|
|
69
|
+
disclaimer: string;
|
|
70
|
+
cached?: boolean;
|
|
71
|
+
replayed?: boolean;
|
|
72
|
+
/** Present when the API signs verdicts. */
|
|
73
|
+
attestation?: Attestation;
|
|
74
|
+
}
|
|
75
|
+
interface Quote {
|
|
76
|
+
subject: Subject;
|
|
77
|
+
policy: string;
|
|
78
|
+
priceUsdc: number;
|
|
79
|
+
ok: boolean;
|
|
80
|
+
upstreamUsdc?: number;
|
|
81
|
+
checks?: {
|
|
82
|
+
check: string;
|
|
83
|
+
intent: string;
|
|
84
|
+
quoteUsdc: number;
|
|
85
|
+
}[];
|
|
86
|
+
dropped?: unknown[];
|
|
87
|
+
refusal?: {
|
|
88
|
+
code: string;
|
|
89
|
+
detail: string;
|
|
90
|
+
checks?: string[];
|
|
91
|
+
quoteUusdc?: number;
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
interface VerifyReport {
|
|
95
|
+
id: string;
|
|
96
|
+
ok: boolean;
|
|
97
|
+
checks: Record<string, boolean>;
|
|
98
|
+
verdictHash: {
|
|
99
|
+
stored: string;
|
|
100
|
+
recomputed: string;
|
|
101
|
+
};
|
|
102
|
+
bomRoot: {
|
|
103
|
+
stored: string;
|
|
104
|
+
recomputed: string;
|
|
105
|
+
};
|
|
106
|
+
receipts: string[];
|
|
107
|
+
problems: string[];
|
|
108
|
+
/** The signer the API checked the attestation against, when it signs verdicts. */
|
|
109
|
+
attester?: string;
|
|
110
|
+
}
|
|
111
|
+
interface BomLine {
|
|
112
|
+
check: string;
|
|
113
|
+
intent: string;
|
|
114
|
+
minerId: string | null;
|
|
115
|
+
minerName: string | null;
|
|
116
|
+
receiptHash: string | null;
|
|
117
|
+
signalHash: string | null;
|
|
118
|
+
amountUsdc: number;
|
|
119
|
+
billed: boolean;
|
|
120
|
+
error: string | null;
|
|
121
|
+
[k: string]: unknown;
|
|
122
|
+
}
|
|
123
|
+
interface Bom {
|
|
124
|
+
id: string;
|
|
125
|
+
root: string;
|
|
126
|
+
items: number;
|
|
127
|
+
verdictHash: string;
|
|
128
|
+
lines: BomLine[];
|
|
129
|
+
}
|
|
130
|
+
/** One server-sent event of a running verdict. */
|
|
131
|
+
type VerdictEvent = {
|
|
132
|
+
type: "plan";
|
|
133
|
+
data: {
|
|
134
|
+
purchases?: {
|
|
135
|
+
check: string;
|
|
136
|
+
intent: string;
|
|
137
|
+
quoteUusdc: number;
|
|
138
|
+
}[];
|
|
139
|
+
dropped?: unknown[];
|
|
140
|
+
[k: string]: unknown;
|
|
141
|
+
};
|
|
142
|
+
} | {
|
|
143
|
+
type: "purchase";
|
|
144
|
+
data: {
|
|
145
|
+
check: string;
|
|
146
|
+
minerId?: string;
|
|
147
|
+
minerName?: string;
|
|
148
|
+
amountUusdc: number;
|
|
149
|
+
receiptHash?: string;
|
|
150
|
+
error?: string;
|
|
151
|
+
[k: string]: unknown;
|
|
152
|
+
};
|
|
153
|
+
} | {
|
|
154
|
+
type: "finding";
|
|
155
|
+
data: Finding;
|
|
156
|
+
} | {
|
|
157
|
+
type: "decision";
|
|
158
|
+
data: {
|
|
159
|
+
decision: {
|
|
160
|
+
verdict: Verdict;
|
|
161
|
+
riskBps: number;
|
|
162
|
+
[k: string]: unknown;
|
|
163
|
+
};
|
|
164
|
+
verdictHash: string;
|
|
165
|
+
[k: string]: unknown;
|
|
166
|
+
};
|
|
167
|
+
} | {
|
|
168
|
+
type: "done";
|
|
169
|
+
data: {
|
|
170
|
+
id?: string;
|
|
171
|
+
[k: string]: unknown;
|
|
172
|
+
};
|
|
173
|
+
} | {
|
|
174
|
+
type: "refused";
|
|
175
|
+
data: {
|
|
176
|
+
code: string;
|
|
177
|
+
detail: string;
|
|
178
|
+
[k: string]: unknown;
|
|
179
|
+
};
|
|
180
|
+
} | {
|
|
181
|
+
type: "error";
|
|
182
|
+
data: {
|
|
183
|
+
message: string;
|
|
184
|
+
[k: string]: unknown;
|
|
185
|
+
};
|
|
186
|
+
};
|
|
187
|
+
/** The Telegraph ask result of a paid call, as returned by any Telegraph client. */
|
|
188
|
+
interface TelegraphAskOutcomeOk {
|
|
189
|
+
ok: true;
|
|
190
|
+
response: {
|
|
191
|
+
miner_id: string;
|
|
192
|
+
result: unknown;
|
|
193
|
+
signal_hash?: string;
|
|
194
|
+
cost_usd?: number;
|
|
195
|
+
};
|
|
196
|
+
receipt: {
|
|
197
|
+
receipt_hash: string;
|
|
198
|
+
} | null;
|
|
199
|
+
amountUusdc: number;
|
|
200
|
+
durationMs: number;
|
|
201
|
+
}
|
|
202
|
+
interface TelegraphAskOutcomeFail {
|
|
203
|
+
ok: false;
|
|
204
|
+
kind: string;
|
|
205
|
+
error: string;
|
|
206
|
+
httpStatus?: number;
|
|
207
|
+
}
|
|
208
|
+
/** Anything that can make one paid Telegraph ask, e.g. TelegraphClient from @skeinlabs/sdk/telegraph. */
|
|
209
|
+
interface TelegraphAsker {
|
|
210
|
+
ask(req: {
|
|
211
|
+
intent: string;
|
|
212
|
+
params?: Record<string, unknown>;
|
|
213
|
+
}, opts: {
|
|
214
|
+
minerId?: string;
|
|
215
|
+
timeoutMs: number;
|
|
216
|
+
}): Promise<TelegraphAskOutcomeOk | TelegraphAskOutcomeFail>;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export type { Attestation as A, Bom as B, CheckStatus as C, Finding as F, Quote as Q, Subject as S, TelegraphAsker as T, VerdictObject as V, VerifyReport as a, VerdictEvent as b, BomLine as c, TelegraphAskOutcomeFail as d, TelegraphAskOutcomeOk as e, Verdict as f };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skeinlabs/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "TypeScript client for Skein token listing verdicts: verdict(), quote(), verify(), stream(), typed errors, retries and a spend cap checked before any payment. Pays with a partner key or per call through Telegraph.",
|
|
6
6
|
"exports": {
|
|
@@ -12,12 +12,17 @@
|
|
|
12
12
|
"types": "./dist/telegraph.d.ts",
|
|
13
13
|
"import": "./dist/telegraph.js"
|
|
14
14
|
},
|
|
15
|
+
"./attest": {
|
|
16
|
+
"types": "./dist/attest.d.ts",
|
|
17
|
+
"import": "./dist/attest.js"
|
|
18
|
+
},
|
|
15
19
|
"./package.json": "./package.json"
|
|
16
20
|
},
|
|
17
21
|
"devDependencies": {
|
|
18
22
|
"tsup": "8.5.0",
|
|
19
23
|
"typescript": "5.9.3",
|
|
20
24
|
"viem": "2.57.5",
|
|
25
|
+
"@skein/engine": "0.1.0",
|
|
21
26
|
"@skein/telegraph": "0.1.0",
|
|
22
27
|
"@skein/api": "0.1.0"
|
|
23
28
|
},
|