confidia-sdk 1.0.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 +74 -0
- package/dist/cjs/src/index.d.ts +3 -0
- package/dist/cjs/src/index.js +20 -0
- package/dist/cjs/src/index.js.map +1 -0
- package/dist/cjs/src/lcp.d.ts +41 -0
- package/dist/cjs/src/lcp.js +118 -0
- package/dist/cjs/src/lcp.js.map +1 -0
- package/dist/cjs/src/policy.d.ts +23 -0
- package/dist/cjs/src/policy.js +48 -0
- package/dist/cjs/src/policy.js.map +1 -0
- package/dist/cjs/src/sdk.test.d.ts +1 -0
- package/dist/cjs/src/sdk.test.js +51 -0
- package/dist/cjs/src/sdk.test.js.map +1 -0
- package/dist/cjs/src/sep10.d.ts +30 -0
- package/dist/cjs/src/sep10.js +49 -0
- package/dist/cjs/src/sep10.js.map +1 -0
- package/dist/esm/src/index.d.ts +3 -0
- package/dist/esm/src/index.js +20 -0
- package/dist/esm/src/index.js.map +1 -0
- package/dist/esm/src/lcp.d.ts +41 -0
- package/dist/esm/src/lcp.js +118 -0
- package/dist/esm/src/lcp.js.map +1 -0
- package/dist/esm/src/policy.d.ts +23 -0
- package/dist/esm/src/policy.js +48 -0
- package/dist/esm/src/policy.js.map +1 -0
- package/dist/esm/src/sdk.test.d.ts +1 -0
- package/dist/esm/src/sdk.test.js +51 -0
- package/dist/esm/src/sdk.test.js.map +1 -0
- package/dist/esm/src/sep10.d.ts +30 -0
- package/dist/esm/src/sep10.js +49 -0
- package/dist/esm/src/sep10.js.map +1 -0
- package/package.json +37 -0
package/README.md
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# confidia-sdk
|
|
2
|
+
|
|
3
|
+
Legal Context Protocol (LCP) client and a compliance policy engine, extracted
|
|
4
|
+
from [Confidia](https://github.com/Eras256/Confidia) — private, compliant
|
|
5
|
+
distribution rails for tokenized USD (USDC/EURC) on Stellar. Live demo:
|
|
6
|
+
[confidia.vercel.app](https://confidia.vercel.app).
|
|
7
|
+
|
|
8
|
+
Everything this package exports is real, dependency-free logic — no mocks, no
|
|
9
|
+
simulated network calls, no fabricated data:
|
|
10
|
+
|
|
11
|
+
- **`LcpClient`** — discovers a counterparty's Legal Context Protocol document
|
|
12
|
+
over a genuine HTTPS fetch, validates its shape, and verifies the linked
|
|
13
|
+
terms document's SHA-256 hash against the declared `atrHash`.
|
|
14
|
+
- **`PolicyEngine`** — evaluates a transaction against compliance rules
|
|
15
|
+
(jurisdiction allow-lists, standard-vs-confidential thresholds, required
|
|
16
|
+
proof types) and returns a decision plus the reasons behind it.
|
|
17
|
+
- **SEP-10 helpers** (`fetchSep10Challenge`, `verifySep10Signature`) — thin,
|
|
18
|
+
typed wrappers around a Stellar SEP-10 web-authentication challenge/response
|
|
19
|
+
flow against your own API.
|
|
20
|
+
|
|
21
|
+
## Install
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install confidia-sdk
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
import { LcpClient, PolicyEngine } from "confidia-sdk";
|
|
31
|
+
|
|
32
|
+
const lcp = new LcpClient();
|
|
33
|
+
|
|
34
|
+
// Real network fetch + real SHA-256 hash verification — no fixtures.
|
|
35
|
+
const doc = await lcp.fetchLegalContext("confidia.vercel.app");
|
|
36
|
+
if (!lcp.validateLegalContext(doc)) {
|
|
37
|
+
throw new Error("Missing required LCP fields");
|
|
38
|
+
}
|
|
39
|
+
const terms = await lcp.fetchTermsDocument(doc.terms);
|
|
40
|
+
const hashMatches = lcp.verifyAtrHash(terms, doc.atrHash); // true
|
|
41
|
+
|
|
42
|
+
const policy = new PolicyEngine();
|
|
43
|
+
const decision = policy.evaluate(
|
|
44
|
+
{ amount: 12000, assetCode: "USDC", jurisdiction: "MX", isAccredited: true },
|
|
45
|
+
{
|
|
46
|
+
maxStandardAmount: 5000,
|
|
47
|
+
requireConfidential: false,
|
|
48
|
+
requiredProofs: ["zkBalance"],
|
|
49
|
+
allowedJurisdictions: ["MX", "US"],
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
// decision.tokenType === "confidential" (amount exceeds maxStandardAmount)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## What this package deliberately does not include
|
|
56
|
+
|
|
57
|
+
Confidia's dashboard also ships real zero-knowledge verification (a deployed
|
|
58
|
+
[Nethermind UltraHonk verifier](https://github.com/NethermindEth) doing
|
|
59
|
+
genuine BN254 pairing checks on Stellar Soroban) and a real on-chain claim
|
|
60
|
+
vault — those are Rust/Soroban contracts, not JS, so they aren't part of this
|
|
61
|
+
npm package. See [`contracts/real-verifier`](https://github.com/Eras256/Confidia/tree/main/contracts/real-verifier)
|
|
62
|
+
and the live Claim Portal for that code and its evidence trail on
|
|
63
|
+
[stellar.expert](https://stellar.expert/explorer/testnet).
|
|
64
|
+
|
|
65
|
+
An earlier internal build of this SDK also included a simulated ZK-proof
|
|
66
|
+
client and a simulated confidential-token wrapper for demo purposes. Those
|
|
67
|
+
were deliberately excluded from this public package — they encoded proofs as
|
|
68
|
+
plain JSON and called an in-memory mock RPC, not real cryptography or a real
|
|
69
|
+
contract, and publishing them under an SDK meant to represent real compliance
|
|
70
|
+
tooling would have been misleading.
|
|
71
|
+
|
|
72
|
+
## License
|
|
73
|
+
|
|
74
|
+
MIT
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./lcp.js"), exports);
|
|
18
|
+
__exportStar(require("./policy.js"), exports);
|
|
19
|
+
__exportStar(require("./sep10.js"), exports);
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,8CAA4B;AAC5B,6CAA2B"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export interface LcpDocument {
|
|
2
|
+
terms: string;
|
|
3
|
+
atrHash: string;
|
|
4
|
+
termsFormat: string;
|
|
5
|
+
acceptanceRequired: boolean;
|
|
6
|
+
jurisdiction?: string;
|
|
7
|
+
disputeResolution?: string;
|
|
8
|
+
consentModel?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface AgreementRecord {
|
|
11
|
+
agentId: string;
|
|
12
|
+
domain: string;
|
|
13
|
+
atrHash: string;
|
|
14
|
+
consentTimestamp: string;
|
|
15
|
+
signature: string;
|
|
16
|
+
status: "signed" | "active" | "disputed";
|
|
17
|
+
}
|
|
18
|
+
export declare class LcpClient {
|
|
19
|
+
/**
|
|
20
|
+
* Discovers and retrieves the legal context from a domain via a genuine
|
|
21
|
+
* network fetch to https://<domain>/.well-known/legal-context.json — no
|
|
22
|
+
* demo-domain special-casing, so behavior is identical for every caller.
|
|
23
|
+
*/
|
|
24
|
+
fetchLegalContext(domain: string): Promise<LcpDocument>;
|
|
25
|
+
/**
|
|
26
|
+
* Fetches the raw terms document referenced by an LcpDocument's `terms` URL.
|
|
27
|
+
*/
|
|
28
|
+
fetchTermsDocument(termsUrl: string): Promise<string>;
|
|
29
|
+
/**
|
|
30
|
+
* Validates LcpDocument according to the protocol rules.
|
|
31
|
+
*/
|
|
32
|
+
validateLegalContext(lcp: any): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Verifies if the terms text SHA-256 matches the expected ATR hash.
|
|
35
|
+
*/
|
|
36
|
+
verifyAtrHash(termsText: string, expectedHash: string): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Signs and creates a verifiable Agreement Record.
|
|
39
|
+
*/
|
|
40
|
+
createAgreementRecord(agentId: string, domain: string, atrHash: string, agentPrivateKey: string): Promise<AgreementRecord>;
|
|
41
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.LcpClient = void 0;
|
|
37
|
+
const crypto = __importStar(require("crypto"));
|
|
38
|
+
// Required fields per the Legal Context Protocol spec v1.0.0.
|
|
39
|
+
const LCP_REQUIRED_FIELDS = ["terms", "atrHash"];
|
|
40
|
+
class LcpClient {
|
|
41
|
+
/**
|
|
42
|
+
* Discovers and retrieves the legal context from a domain via a genuine
|
|
43
|
+
* network fetch to https://<domain>/.well-known/legal-context.json — no
|
|
44
|
+
* demo-domain special-casing, so behavior is identical for every caller.
|
|
45
|
+
*/
|
|
46
|
+
async fetchLegalContext(domain) {
|
|
47
|
+
const url = `https://${domain}/.well-known/legal-context.json`;
|
|
48
|
+
const response = await fetch(url);
|
|
49
|
+
if (!response.ok) {
|
|
50
|
+
throw new Error(`Failed to fetch LCP document: ${response.statusText}`);
|
|
51
|
+
}
|
|
52
|
+
const text = await response.text();
|
|
53
|
+
try {
|
|
54
|
+
return JSON.parse(text);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// A 2xx response that isn't JSON usually means the domain has no real
|
|
58
|
+
// LCP document at this path (e.g. a SPA/catch-all route serving its
|
|
59
|
+
// index.html for any unknown path) — surface that plainly instead of
|
|
60
|
+
// leaking a raw "Unexpected token '<'" parse error.
|
|
61
|
+
throw new Error(`Domain does not publish a valid legal-context.json document at ${url}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Fetches the raw terms document referenced by an LcpDocument's `terms` URL.
|
|
66
|
+
*/
|
|
67
|
+
async fetchTermsDocument(termsUrl) {
|
|
68
|
+
const response = await fetch(termsUrl);
|
|
69
|
+
if (!response.ok) {
|
|
70
|
+
throw new Error(`Failed to fetch terms document: ${response.statusText}`);
|
|
71
|
+
}
|
|
72
|
+
return await response.text();
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Validates LcpDocument according to the protocol rules.
|
|
76
|
+
*/
|
|
77
|
+
validateLegalContext(lcp) {
|
|
78
|
+
for (const field of LCP_REQUIRED_FIELDS) {
|
|
79
|
+
if (!lcp || typeof lcp !== "object" || !(field in lcp)) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Verifies if the terms text SHA-256 matches the expected ATR hash.
|
|
87
|
+
*/
|
|
88
|
+
verifyAtrHash(termsText, expectedHash) {
|
|
89
|
+
// Standardize newlines before hashing
|
|
90
|
+
const normalized = termsText.replace(/\r\n/g, "\n");
|
|
91
|
+
const hash = crypto.createHash("sha256").update(normalized).digest("hex");
|
|
92
|
+
// Clean expected hash (remove prefix 0x if present)
|
|
93
|
+
const cleanExpected = expectedHash.replace(/^0x/, "");
|
|
94
|
+
return hash === cleanExpected;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Signs and creates a verifiable Agreement Record.
|
|
98
|
+
*/
|
|
99
|
+
async createAgreementRecord(agentId, domain, atrHash, agentPrivateKey) {
|
|
100
|
+
const consentTimestamp = new Date().toISOString();
|
|
101
|
+
const payload = `${agentId}:${domain}:${atrHash}:${consentTimestamp}`;
|
|
102
|
+
// Compute signature using mock/SHA256 signature
|
|
103
|
+
const signature = crypto
|
|
104
|
+
.createHmac("sha256", agentPrivateKey)
|
|
105
|
+
.update(payload)
|
|
106
|
+
.digest("hex");
|
|
107
|
+
return {
|
|
108
|
+
agentId,
|
|
109
|
+
domain,
|
|
110
|
+
atrHash,
|
|
111
|
+
consentTimestamp,
|
|
112
|
+
signature,
|
|
113
|
+
status: "signed"
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
exports.LcpClient = LcpClient;
|
|
118
|
+
//# sourceMappingURL=lcp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lcp.js","sourceRoot":"","sources":["../../../src/lcp.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+CAAiC;AAEjC,8DAA8D;AAC9D,MAAM,mBAAmB,GAAG,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;AAqBjD,MAAa,SAAS;IACpB;;;;OAIG;IACI,KAAK,CAAC,iBAAiB,CAAC,MAAc;QAC3C,MAAM,GAAG,GAAG,WAAW,MAAM,iCAAiC,CAAC;QAC/D,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,iCAAiC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;QAC1E,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAgB,CAAC;QACzC,CAAC;QAAC,MAAM,CAAC;YACP,sEAAsE;YACtE,oEAAoE;YACpE,qEAAqE;YACrE,oDAAoD;YACpD,MAAM,IAAI,KAAK,CAAC,kEAAkE,GAAG,EAAE,CAAC,CAAC;QAC3F,CAAC;IACH,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,kBAAkB,CAAC,QAAgB;QAC9C,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAC;QACvC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,mCAAmC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;QAC5E,CAAC;QACD,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC/B,CAAC;IAED;;OAEG;IACI,oBAAoB,CAAC,GAAQ;QAClC,KAAK,MAAM,KAAK,IAAI,mBAAmB,EAAE,CAAC;YACxC,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,CAAC,KAAK,IAAI,GAAG,CAAC,EAAE,CAAC;gBACvD,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACI,aAAa,CAAC,SAAiB,EAAE,YAAoB;QAC1D,sCAAsC;QACtC,MAAM,UAAU,GAAG,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACpD,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAE1E,oDAAoD;QACpD,MAAM,aAAa,GAAG,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACtD,OAAO,IAAI,KAAK,aAAa,CAAC;IAChC,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,qBAAqB,CAChC,OAAe,EACf,MAAc,EACd,OAAe,EACf,eAAuB;QAEvB,MAAM,gBAAgB,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAClD,MAAM,OAAO,GAAG,GAAG,OAAO,IAAI,MAAM,IAAI,OAAO,IAAI,gBAAgB,EAAE,CAAC;QAEtE,gDAAgD;QAChD,MAAM,SAAS,GAAG,MAAM;aACrB,UAAU,CAAC,QAAQ,EAAE,eAAe,CAAC;aACrC,MAAM,CAAC,OAAO,CAAC;aACf,MAAM,CAAC,KAAK,CAAC,CAAC;QAEjB,OAAO;YACL,OAAO;YACP,MAAM;YACN,OAAO;YACP,gBAAgB;YAChB,SAAS;YACT,MAAM,EAAE,QAAQ;SACjB,CAAC;IACJ,CAAC;CACF;AAvFD,8BAuFC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface PolicyRules {
|
|
2
|
+
maxStandardAmount: number;
|
|
3
|
+
requireConfidential: boolean;
|
|
4
|
+
requiredProofs: string[];
|
|
5
|
+
allowedJurisdictions: string[];
|
|
6
|
+
}
|
|
7
|
+
export interface PolicyEvaluationResult {
|
|
8
|
+
allowed: boolean;
|
|
9
|
+
tokenType: "standard" | "confidential";
|
|
10
|
+
requiredProofs: string[];
|
|
11
|
+
reasons: string[];
|
|
12
|
+
}
|
|
13
|
+
export declare class PolicyEngine {
|
|
14
|
+
/**
|
|
15
|
+
* Evaluates if a transaction satisfies global policy rules and determines ZK requirements.
|
|
16
|
+
*/
|
|
17
|
+
evaluate(transaction: {
|
|
18
|
+
amount: number;
|
|
19
|
+
assetCode: string;
|
|
20
|
+
jurisdiction?: string;
|
|
21
|
+
isAccredited?: boolean;
|
|
22
|
+
}, policy: PolicyRules): PolicyEvaluationResult;
|
|
23
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PolicyEngine = void 0;
|
|
4
|
+
class PolicyEngine {
|
|
5
|
+
/**
|
|
6
|
+
* Evaluates if a transaction satisfies global policy rules and determines ZK requirements.
|
|
7
|
+
*/
|
|
8
|
+
evaluate(transaction, policy) {
|
|
9
|
+
const reasons = [];
|
|
10
|
+
let allowed = true;
|
|
11
|
+
let tokenType = "standard";
|
|
12
|
+
const requiredProofs = [...policy.requiredProofs];
|
|
13
|
+
// Check jurisdiction constraints
|
|
14
|
+
if (transaction.jurisdiction && policy.allowedJurisdictions.length > 0) {
|
|
15
|
+
if (!policy.allowedJurisdictions.includes(transaction.jurisdiction)) {
|
|
16
|
+
allowed = false;
|
|
17
|
+
reasons.push(`Jurisdiction ${transaction.jurisdiction} is not authorized by the compliance policy.`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
// Determine standard vs confidential token selection
|
|
21
|
+
if (policy.requireConfidential || transaction.amount > policy.maxStandardAmount) {
|
|
22
|
+
tokenType = "confidential";
|
|
23
|
+
reasons.push(`Transaction amount ${transaction.amount} exceeds public threshold ${policy.maxStandardAmount} or privacy is explicitly mandated.`);
|
|
24
|
+
}
|
|
25
|
+
// Accumulate required ZK proofs based on transaction parameters
|
|
26
|
+
if (tokenType === "confidential") {
|
|
27
|
+
if (!requiredProofs.includes("zkBalance")) {
|
|
28
|
+
requiredProofs.push("zkBalance");
|
|
29
|
+
}
|
|
30
|
+
if (transaction.amount > policy.maxStandardAmount * 2 && !requiredProofs.includes("zkExposure")) {
|
|
31
|
+
requiredProofs.push("zkExposure");
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// Add zkEligibility if accreditation or compliance checks are required
|
|
35
|
+
if (policy.requiredProofs.includes("zkEligibility") && !transaction.isAccredited) {
|
|
36
|
+
allowed = false;
|
|
37
|
+
reasons.push("ZK accreditation eligibility proof is required but account eligibility state is false.");
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
allowed,
|
|
41
|
+
tokenType,
|
|
42
|
+
requiredProofs,
|
|
43
|
+
reasons
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
exports.PolicyEngine = PolicyEngine;
|
|
48
|
+
//# sourceMappingURL=policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../../../src/policy.ts"],"names":[],"mappings":";;;AAcA,MAAa,YAAY;IACvB;;OAEG;IACI,QAAQ,CACb,WAKC,EACD,MAAmB;QAEnB,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,IAAI,OAAO,GAAG,IAAI,CAAC;QACnB,IAAI,SAAS,GAAgC,UAAU,CAAC;QACxD,MAAM,cAAc,GAAa,CAAC,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC;QAE5D,iCAAiC;QACjC,IAAI,WAAW,CAAC,YAAY,IAAI,MAAM,CAAC,oBAAoB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvE,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,QAAQ,CAAC,WAAW,CAAC,YAAY,CAAC,EAAE,CAAC;gBACpE,OAAO,GAAG,KAAK,CAAC;gBAChB,OAAO,CAAC,IAAI,CAAC,gBAAgB,WAAW,CAAC,YAAY,8CAA8C,CAAC,CAAC;YACvG,CAAC;QACH,CAAC;QAED,qDAAqD;QACrD,IAAI,MAAM,CAAC,mBAAmB,IAAI,WAAW,CAAC,MAAM,GAAG,MAAM,CAAC,iBAAiB,EAAE,CAAC;YAChF,SAAS,GAAG,cAAc,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC,sBAAsB,WAAW,CAAC,MAAM,6BAA6B,MAAM,CAAC,iBAAiB,qCAAqC,CAAC,CAAC;QACnJ,CAAC;QAED,gEAAgE;QAChE,IAAI,SAAS,KAAK,cAAc,EAAE,CAAC;YACjC,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC1C,cAAc,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACnC,CAAC;YACD,IAAI,WAAW,CAAC,MAAM,GAAG,MAAM,CAAC,iBAAiB,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;gBAChG,cAAc,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACpC,CAAC;QACH,CAAC;QAED,uEAAuE;QACvE,IAAI,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC;YACjF,OAAO,GAAG,KAAK,CAAC;YAChB,OAAO,CAAC,IAAI,CAAC,wFAAwF,CAAC,CAAC;QACzG,CAAC;QAED,OAAO;YACL,OAAO;YACP,SAAS;YACT,cAAc;YACd,OAAO;SACR,CAAC;IACJ,CAAC;CACF;AAvDD,oCAuDC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const index_js_1 = require("./index.js");
|
|
5
|
+
(0, vitest_1.describe)("Confidia SDK Integration Verification", () => {
|
|
6
|
+
const lcpClient = new index_js_1.LcpClient();
|
|
7
|
+
const policyEngine = new index_js_1.PolicyEngine();
|
|
8
|
+
(0, vitest_1.describe)("LcpClient", () => {
|
|
9
|
+
(0, vitest_1.it)("should fetch and validate a real LCP config from a live domain", async () => {
|
|
10
|
+
const lcp = await lcpClient.fetchLegalContext("confidia.vercel.app");
|
|
11
|
+
(0, vitest_1.expect)(lcp.jurisdiction).toBe("US-DE");
|
|
12
|
+
(0, vitest_1.expect)(lcpClient.validateLegalContext(lcp)).toBe(true);
|
|
13
|
+
});
|
|
14
|
+
(0, vitest_1.it)("should check ATR terms document SHA-256 hash match", async () => {
|
|
15
|
+
const lcp = await lcpClient.fetchLegalContext("confidia.vercel.app");
|
|
16
|
+
const terms = await lcpClient.fetchTermsDocument(lcp.terms);
|
|
17
|
+
(0, vitest_1.expect)(lcpClient.verifyAtrHash(terms, lcp.atrHash)).toBe(true);
|
|
18
|
+
(0, vitest_1.expect)(lcpClient.verifyAtrHash("altered terms", lcp.atrHash)).toBe(false);
|
|
19
|
+
});
|
|
20
|
+
(0, vitest_1.it)("should sign a verifiable Agreement Record", async () => {
|
|
21
|
+
const record = await lcpClient.createAgreementRecord("agent-1", "confidia.vercel.app", "mock_atr_hash", "secret_priv_key");
|
|
22
|
+
(0, vitest_1.expect)(record.agentId).toBe("agent-1");
|
|
23
|
+
(0, vitest_1.expect)(record.status).toBe("signed");
|
|
24
|
+
(0, vitest_1.expect)(record.signature).toBeDefined();
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
(0, vitest_1.describe)("PolicyEngine", () => {
|
|
28
|
+
const rules = {
|
|
29
|
+
maxStandardAmount: 5000,
|
|
30
|
+
requireConfidential: false,
|
|
31
|
+
requiredProofs: ["zkBalance"],
|
|
32
|
+
allowedJurisdictions: ["MX", "US"]
|
|
33
|
+
};
|
|
34
|
+
(0, vitest_1.it)("should choose standard token standard below threshold", () => {
|
|
35
|
+
const evalRes = policyEngine.evaluate({ amount: 3000, assetCode: "USDC", jurisdiction: "MX", isAccredited: true }, rules);
|
|
36
|
+
(0, vitest_1.expect)(evalRes.allowed).toBe(true);
|
|
37
|
+
(0, vitest_1.expect)(evalRes.tokenType).toBe("standard");
|
|
38
|
+
});
|
|
39
|
+
(0, vitest_1.it)("should choose confidential token standard above threshold", () => {
|
|
40
|
+
const evalRes = policyEngine.evaluate({ amount: 12000, assetCode: "USDC", jurisdiction: "MX", isAccredited: true }, rules);
|
|
41
|
+
(0, vitest_1.expect)(evalRes.allowed).toBe(true);
|
|
42
|
+
(0, vitest_1.expect)(evalRes.tokenType).toBe("confidential");
|
|
43
|
+
(0, vitest_1.expect)(evalRes.requiredProofs).toContain("zkBalance");
|
|
44
|
+
});
|
|
45
|
+
(0, vitest_1.it)("should block transacting in unauthorized jurisdictions", () => {
|
|
46
|
+
const evalRes = policyEngine.evaluate({ amount: 2000, assetCode: "USDC", jurisdiction: "CA" }, rules);
|
|
47
|
+
(0, vitest_1.expect)(evalRes.allowed).toBe(false);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
//# sourceMappingURL=sdk.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk.test.js","sourceRoot":"","sources":["../../../src/sdk.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SEP-10 Web Authentication types and client helpers for Confidia SDK.
|
|
3
|
+
* These types are shared between the frontend (wallet-kit, auth.ts) and backend (server.ts).
|
|
4
|
+
*/
|
|
5
|
+
export interface Sep10Challenge {
|
|
6
|
+
/** Base64-encoded XDR of the unsigned challenge transaction */
|
|
7
|
+
transaction: string;
|
|
8
|
+
/** Stellar network passphrase the transaction was built for */
|
|
9
|
+
network_passphrase: string;
|
|
10
|
+
}
|
|
11
|
+
export interface Sep10VerifyRequest {
|
|
12
|
+
/** Signed XDR envelope returned by the wallet */
|
|
13
|
+
transaction: string;
|
|
14
|
+
}
|
|
15
|
+
export interface Sep10Session {
|
|
16
|
+
/** JWT token issued after successful SEP-10 challenge verification */
|
|
17
|
+
token: string;
|
|
18
|
+
/** Stellar G-address of the authenticated account */
|
|
19
|
+
address: string;
|
|
20
|
+
/** Unix timestamp when the session expires */
|
|
21
|
+
expiresAt: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Fetches a SEP-10 challenge for the given Stellar address from a Confidia API endpoint.
|
|
25
|
+
*/
|
|
26
|
+
export declare function fetchSep10Challenge(apiBase: string, address: string): Promise<Sep10Challenge>;
|
|
27
|
+
/**
|
|
28
|
+
* Submits a signed SEP-10 challenge transaction to receive a session JWT.
|
|
29
|
+
*/
|
|
30
|
+
export declare function verifySep10Signature(apiBase: string, signedXdr: string): Promise<Sep10Session>;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* SEP-10 Web Authentication types and client helpers for Confidia SDK.
|
|
4
|
+
* These types are shared between the frontend (wallet-kit, auth.ts) and backend (server.ts).
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.fetchSep10Challenge = fetchSep10Challenge;
|
|
8
|
+
exports.verifySep10Signature = verifySep10Signature;
|
|
9
|
+
/**
|
|
10
|
+
* Fetches a SEP-10 challenge for the given Stellar address from a Confidia API endpoint.
|
|
11
|
+
*/
|
|
12
|
+
async function fetchSep10Challenge(apiBase, address) {
|
|
13
|
+
const res = await fetch(`${apiBase}/auth/challenge?address=${address}`);
|
|
14
|
+
const text = await res.text();
|
|
15
|
+
try {
|
|
16
|
+
const data = JSON.parse(text);
|
|
17
|
+
if (data.error)
|
|
18
|
+
throw new Error(data.error);
|
|
19
|
+
return data;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
throw new Error(`SEP-10 challenge endpoint returned non-JSON (status ${res.status}). Is the API running?`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Submits a signed SEP-10 challenge transaction to receive a session JWT.
|
|
27
|
+
*/
|
|
28
|
+
async function verifySep10Signature(apiBase, signedXdr) {
|
|
29
|
+
const res = await fetch(`${apiBase}/auth/verify`, {
|
|
30
|
+
method: "POST",
|
|
31
|
+
headers: { "Content-Type": "application/json" },
|
|
32
|
+
body: JSON.stringify({ transaction: signedXdr })
|
|
33
|
+
});
|
|
34
|
+
const text = await res.text();
|
|
35
|
+
try {
|
|
36
|
+
const data = JSON.parse(text);
|
|
37
|
+
if (data.error)
|
|
38
|
+
throw new Error(data.error);
|
|
39
|
+
return {
|
|
40
|
+
token: data.token,
|
|
41
|
+
address: data.address || "",
|
|
42
|
+
expiresAt: Math.floor(Date.now() / 1000) + 3600
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
throw new Error(`SEP-10 verify endpoint returned non-JSON (status ${res.status}). Is the API running?`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=sep10.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sep10.js","sourceRoot":"","sources":["../../../src/sep10.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AA0BH,kDAeC;AAKD,oDAuBC;AA9CD;;GAEG;AACI,KAAK,UAAU,mBAAmB,CACvC,OAAe,EACf,OAAe;IAEf,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,2BAA2B,OAAO,EAAE,CAAC,CAAC;IACxE,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5C,OAAO,IAAsB,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,uDAAuD,GAAG,CAAC,MAAM,wBAAwB,CAC1F,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,oBAAoB,CACxC,OAAe,EACf,SAAiB;IAEjB,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,cAAc,EAAE;QAChD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,SAAS,EAA+B,CAAC;KAC9E,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5C,OAAO;YACL,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,EAAE;YAC3B,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI;SAChD,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,oDAAoD,GAAG,CAAC,MAAM,wBAAwB,CACvF,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./lcp.js"), exports);
|
|
18
|
+
__exportStar(require("./policy.js"), exports);
|
|
19
|
+
__exportStar(require("./sep10.js"), exports);
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,8CAA4B;AAC5B,6CAA2B"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export interface LcpDocument {
|
|
2
|
+
terms: string;
|
|
3
|
+
atrHash: string;
|
|
4
|
+
termsFormat: string;
|
|
5
|
+
acceptanceRequired: boolean;
|
|
6
|
+
jurisdiction?: string;
|
|
7
|
+
disputeResolution?: string;
|
|
8
|
+
consentModel?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface AgreementRecord {
|
|
11
|
+
agentId: string;
|
|
12
|
+
domain: string;
|
|
13
|
+
atrHash: string;
|
|
14
|
+
consentTimestamp: string;
|
|
15
|
+
signature: string;
|
|
16
|
+
status: "signed" | "active" | "disputed";
|
|
17
|
+
}
|
|
18
|
+
export declare class LcpClient {
|
|
19
|
+
/**
|
|
20
|
+
* Discovers and retrieves the legal context from a domain via a genuine
|
|
21
|
+
* network fetch to https://<domain>/.well-known/legal-context.json — no
|
|
22
|
+
* demo-domain special-casing, so behavior is identical for every caller.
|
|
23
|
+
*/
|
|
24
|
+
fetchLegalContext(domain: string): Promise<LcpDocument>;
|
|
25
|
+
/**
|
|
26
|
+
* Fetches the raw terms document referenced by an LcpDocument's `terms` URL.
|
|
27
|
+
*/
|
|
28
|
+
fetchTermsDocument(termsUrl: string): Promise<string>;
|
|
29
|
+
/**
|
|
30
|
+
* Validates LcpDocument according to the protocol rules.
|
|
31
|
+
*/
|
|
32
|
+
validateLegalContext(lcp: any): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Verifies if the terms text SHA-256 matches the expected ATR hash.
|
|
35
|
+
*/
|
|
36
|
+
verifyAtrHash(termsText: string, expectedHash: string): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Signs and creates a verifiable Agreement Record.
|
|
39
|
+
*/
|
|
40
|
+
createAgreementRecord(agentId: string, domain: string, atrHash: string, agentPrivateKey: string): Promise<AgreementRecord>;
|
|
41
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.LcpClient = void 0;
|
|
37
|
+
const crypto = __importStar(require("crypto"));
|
|
38
|
+
// Required fields per the Legal Context Protocol spec v1.0.0.
|
|
39
|
+
const LCP_REQUIRED_FIELDS = ["terms", "atrHash"];
|
|
40
|
+
class LcpClient {
|
|
41
|
+
/**
|
|
42
|
+
* Discovers and retrieves the legal context from a domain via a genuine
|
|
43
|
+
* network fetch to https://<domain>/.well-known/legal-context.json — no
|
|
44
|
+
* demo-domain special-casing, so behavior is identical for every caller.
|
|
45
|
+
*/
|
|
46
|
+
async fetchLegalContext(domain) {
|
|
47
|
+
const url = `https://${domain}/.well-known/legal-context.json`;
|
|
48
|
+
const response = await fetch(url);
|
|
49
|
+
if (!response.ok) {
|
|
50
|
+
throw new Error(`Failed to fetch LCP document: ${response.statusText}`);
|
|
51
|
+
}
|
|
52
|
+
const text = await response.text();
|
|
53
|
+
try {
|
|
54
|
+
return JSON.parse(text);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// A 2xx response that isn't JSON usually means the domain has no real
|
|
58
|
+
// LCP document at this path (e.g. a SPA/catch-all route serving its
|
|
59
|
+
// index.html for any unknown path) — surface that plainly instead of
|
|
60
|
+
// leaking a raw "Unexpected token '<'" parse error.
|
|
61
|
+
throw new Error(`Domain does not publish a valid legal-context.json document at ${url}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Fetches the raw terms document referenced by an LcpDocument's `terms` URL.
|
|
66
|
+
*/
|
|
67
|
+
async fetchTermsDocument(termsUrl) {
|
|
68
|
+
const response = await fetch(termsUrl);
|
|
69
|
+
if (!response.ok) {
|
|
70
|
+
throw new Error(`Failed to fetch terms document: ${response.statusText}`);
|
|
71
|
+
}
|
|
72
|
+
return await response.text();
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Validates LcpDocument according to the protocol rules.
|
|
76
|
+
*/
|
|
77
|
+
validateLegalContext(lcp) {
|
|
78
|
+
for (const field of LCP_REQUIRED_FIELDS) {
|
|
79
|
+
if (!lcp || typeof lcp !== "object" || !(field in lcp)) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Verifies if the terms text SHA-256 matches the expected ATR hash.
|
|
87
|
+
*/
|
|
88
|
+
verifyAtrHash(termsText, expectedHash) {
|
|
89
|
+
// Standardize newlines before hashing
|
|
90
|
+
const normalized = termsText.replace(/\r\n/g, "\n");
|
|
91
|
+
const hash = crypto.createHash("sha256").update(normalized).digest("hex");
|
|
92
|
+
// Clean expected hash (remove prefix 0x if present)
|
|
93
|
+
const cleanExpected = expectedHash.replace(/^0x/, "");
|
|
94
|
+
return hash === cleanExpected;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Signs and creates a verifiable Agreement Record.
|
|
98
|
+
*/
|
|
99
|
+
async createAgreementRecord(agentId, domain, atrHash, agentPrivateKey) {
|
|
100
|
+
const consentTimestamp = new Date().toISOString();
|
|
101
|
+
const payload = `${agentId}:${domain}:${atrHash}:${consentTimestamp}`;
|
|
102
|
+
// Compute signature using mock/SHA256 signature
|
|
103
|
+
const signature = crypto
|
|
104
|
+
.createHmac("sha256", agentPrivateKey)
|
|
105
|
+
.update(payload)
|
|
106
|
+
.digest("hex");
|
|
107
|
+
return {
|
|
108
|
+
agentId,
|
|
109
|
+
domain,
|
|
110
|
+
atrHash,
|
|
111
|
+
consentTimestamp,
|
|
112
|
+
signature,
|
|
113
|
+
status: "signed"
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
exports.LcpClient = LcpClient;
|
|
118
|
+
//# sourceMappingURL=lcp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lcp.js","sourceRoot":"","sources":["../../../src/lcp.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+CAAiC;AAEjC,8DAA8D;AAC9D,MAAM,mBAAmB,GAAG,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;AAqBjD,MAAa,SAAS;IACpB;;;;OAIG;IACI,KAAK,CAAC,iBAAiB,CAAC,MAAc;QAC3C,MAAM,GAAG,GAAG,WAAW,MAAM,iCAAiC,CAAC;QAC/D,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,iCAAiC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;QAC1E,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAgB,CAAC;QACzC,CAAC;QAAC,MAAM,CAAC;YACP,sEAAsE;YACtE,oEAAoE;YACpE,qEAAqE;YACrE,oDAAoD;YACpD,MAAM,IAAI,KAAK,CAAC,kEAAkE,GAAG,EAAE,CAAC,CAAC;QAC3F,CAAC;IACH,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,kBAAkB,CAAC,QAAgB;QAC9C,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAC;QACvC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,mCAAmC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;QAC5E,CAAC;QACD,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC/B,CAAC;IAED;;OAEG;IACI,oBAAoB,CAAC,GAAQ;QAClC,KAAK,MAAM,KAAK,IAAI,mBAAmB,EAAE,CAAC;YACxC,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,CAAC,KAAK,IAAI,GAAG,CAAC,EAAE,CAAC;gBACvD,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACI,aAAa,CAAC,SAAiB,EAAE,YAAoB;QAC1D,sCAAsC;QACtC,MAAM,UAAU,GAAG,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACpD,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAE1E,oDAAoD;QACpD,MAAM,aAAa,GAAG,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACtD,OAAO,IAAI,KAAK,aAAa,CAAC;IAChC,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,qBAAqB,CAChC,OAAe,EACf,MAAc,EACd,OAAe,EACf,eAAuB;QAEvB,MAAM,gBAAgB,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAClD,MAAM,OAAO,GAAG,GAAG,OAAO,IAAI,MAAM,IAAI,OAAO,IAAI,gBAAgB,EAAE,CAAC;QAEtE,gDAAgD;QAChD,MAAM,SAAS,GAAG,MAAM;aACrB,UAAU,CAAC,QAAQ,EAAE,eAAe,CAAC;aACrC,MAAM,CAAC,OAAO,CAAC;aACf,MAAM,CAAC,KAAK,CAAC,CAAC;QAEjB,OAAO;YACL,OAAO;YACP,MAAM;YACN,OAAO;YACP,gBAAgB;YAChB,SAAS;YACT,MAAM,EAAE,QAAQ;SACjB,CAAC;IACJ,CAAC;CACF;AAvFD,8BAuFC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface PolicyRules {
|
|
2
|
+
maxStandardAmount: number;
|
|
3
|
+
requireConfidential: boolean;
|
|
4
|
+
requiredProofs: string[];
|
|
5
|
+
allowedJurisdictions: string[];
|
|
6
|
+
}
|
|
7
|
+
export interface PolicyEvaluationResult {
|
|
8
|
+
allowed: boolean;
|
|
9
|
+
tokenType: "standard" | "confidential";
|
|
10
|
+
requiredProofs: string[];
|
|
11
|
+
reasons: string[];
|
|
12
|
+
}
|
|
13
|
+
export declare class PolicyEngine {
|
|
14
|
+
/**
|
|
15
|
+
* Evaluates if a transaction satisfies global policy rules and determines ZK requirements.
|
|
16
|
+
*/
|
|
17
|
+
evaluate(transaction: {
|
|
18
|
+
amount: number;
|
|
19
|
+
assetCode: string;
|
|
20
|
+
jurisdiction?: string;
|
|
21
|
+
isAccredited?: boolean;
|
|
22
|
+
}, policy: PolicyRules): PolicyEvaluationResult;
|
|
23
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PolicyEngine = void 0;
|
|
4
|
+
class PolicyEngine {
|
|
5
|
+
/**
|
|
6
|
+
* Evaluates if a transaction satisfies global policy rules and determines ZK requirements.
|
|
7
|
+
*/
|
|
8
|
+
evaluate(transaction, policy) {
|
|
9
|
+
const reasons = [];
|
|
10
|
+
let allowed = true;
|
|
11
|
+
let tokenType = "standard";
|
|
12
|
+
const requiredProofs = [...policy.requiredProofs];
|
|
13
|
+
// Check jurisdiction constraints
|
|
14
|
+
if (transaction.jurisdiction && policy.allowedJurisdictions.length > 0) {
|
|
15
|
+
if (!policy.allowedJurisdictions.includes(transaction.jurisdiction)) {
|
|
16
|
+
allowed = false;
|
|
17
|
+
reasons.push(`Jurisdiction ${transaction.jurisdiction} is not authorized by the compliance policy.`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
// Determine standard vs confidential token selection
|
|
21
|
+
if (policy.requireConfidential || transaction.amount > policy.maxStandardAmount) {
|
|
22
|
+
tokenType = "confidential";
|
|
23
|
+
reasons.push(`Transaction amount ${transaction.amount} exceeds public threshold ${policy.maxStandardAmount} or privacy is explicitly mandated.`);
|
|
24
|
+
}
|
|
25
|
+
// Accumulate required ZK proofs based on transaction parameters
|
|
26
|
+
if (tokenType === "confidential") {
|
|
27
|
+
if (!requiredProofs.includes("zkBalance")) {
|
|
28
|
+
requiredProofs.push("zkBalance");
|
|
29
|
+
}
|
|
30
|
+
if (transaction.amount > policy.maxStandardAmount * 2 && !requiredProofs.includes("zkExposure")) {
|
|
31
|
+
requiredProofs.push("zkExposure");
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// Add zkEligibility if accreditation or compliance checks are required
|
|
35
|
+
if (policy.requiredProofs.includes("zkEligibility") && !transaction.isAccredited) {
|
|
36
|
+
allowed = false;
|
|
37
|
+
reasons.push("ZK accreditation eligibility proof is required but account eligibility state is false.");
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
allowed,
|
|
41
|
+
tokenType,
|
|
42
|
+
requiredProofs,
|
|
43
|
+
reasons
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
exports.PolicyEngine = PolicyEngine;
|
|
48
|
+
//# sourceMappingURL=policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../../../src/policy.ts"],"names":[],"mappings":";;;AAcA,MAAa,YAAY;IACvB;;OAEG;IACI,QAAQ,CACb,WAKC,EACD,MAAmB;QAEnB,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,IAAI,OAAO,GAAG,IAAI,CAAC;QACnB,IAAI,SAAS,GAAgC,UAAU,CAAC;QACxD,MAAM,cAAc,GAAa,CAAC,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC;QAE5D,iCAAiC;QACjC,IAAI,WAAW,CAAC,YAAY,IAAI,MAAM,CAAC,oBAAoB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvE,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,QAAQ,CAAC,WAAW,CAAC,YAAY,CAAC,EAAE,CAAC;gBACpE,OAAO,GAAG,KAAK,CAAC;gBAChB,OAAO,CAAC,IAAI,CAAC,gBAAgB,WAAW,CAAC,YAAY,8CAA8C,CAAC,CAAC;YACvG,CAAC;QACH,CAAC;QAED,qDAAqD;QACrD,IAAI,MAAM,CAAC,mBAAmB,IAAI,WAAW,CAAC,MAAM,GAAG,MAAM,CAAC,iBAAiB,EAAE,CAAC;YAChF,SAAS,GAAG,cAAc,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC,sBAAsB,WAAW,CAAC,MAAM,6BAA6B,MAAM,CAAC,iBAAiB,qCAAqC,CAAC,CAAC;QACnJ,CAAC;QAED,gEAAgE;QAChE,IAAI,SAAS,KAAK,cAAc,EAAE,CAAC;YACjC,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC1C,cAAc,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACnC,CAAC;YACD,IAAI,WAAW,CAAC,MAAM,GAAG,MAAM,CAAC,iBAAiB,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;gBAChG,cAAc,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACpC,CAAC;QACH,CAAC;QAED,uEAAuE;QACvE,IAAI,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC;YACjF,OAAO,GAAG,KAAK,CAAC;YAChB,OAAO,CAAC,IAAI,CAAC,wFAAwF,CAAC,CAAC;QACzG,CAAC;QAED,OAAO;YACL,OAAO;YACP,SAAS;YACT,cAAc;YACd,OAAO;SACR,CAAC;IACJ,CAAC;CACF;AAvDD,oCAuDC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const index_js_1 = require("./index.js");
|
|
5
|
+
(0, vitest_1.describe)("Confidia SDK Integration Verification", () => {
|
|
6
|
+
const lcpClient = new index_js_1.LcpClient();
|
|
7
|
+
const policyEngine = new index_js_1.PolicyEngine();
|
|
8
|
+
(0, vitest_1.describe)("LcpClient", () => {
|
|
9
|
+
(0, vitest_1.it)("should fetch and validate a real LCP config from a live domain", async () => {
|
|
10
|
+
const lcp = await lcpClient.fetchLegalContext("confidia.vercel.app");
|
|
11
|
+
(0, vitest_1.expect)(lcp.jurisdiction).toBe("US-DE");
|
|
12
|
+
(0, vitest_1.expect)(lcpClient.validateLegalContext(lcp)).toBe(true);
|
|
13
|
+
});
|
|
14
|
+
(0, vitest_1.it)("should check ATR terms document SHA-256 hash match", async () => {
|
|
15
|
+
const lcp = await lcpClient.fetchLegalContext("confidia.vercel.app");
|
|
16
|
+
const terms = await lcpClient.fetchTermsDocument(lcp.terms);
|
|
17
|
+
(0, vitest_1.expect)(lcpClient.verifyAtrHash(terms, lcp.atrHash)).toBe(true);
|
|
18
|
+
(0, vitest_1.expect)(lcpClient.verifyAtrHash("altered terms", lcp.atrHash)).toBe(false);
|
|
19
|
+
});
|
|
20
|
+
(0, vitest_1.it)("should sign a verifiable Agreement Record", async () => {
|
|
21
|
+
const record = await lcpClient.createAgreementRecord("agent-1", "confidia.vercel.app", "mock_atr_hash", "secret_priv_key");
|
|
22
|
+
(0, vitest_1.expect)(record.agentId).toBe("agent-1");
|
|
23
|
+
(0, vitest_1.expect)(record.status).toBe("signed");
|
|
24
|
+
(0, vitest_1.expect)(record.signature).toBeDefined();
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
(0, vitest_1.describe)("PolicyEngine", () => {
|
|
28
|
+
const rules = {
|
|
29
|
+
maxStandardAmount: 5000,
|
|
30
|
+
requireConfidential: false,
|
|
31
|
+
requiredProofs: ["zkBalance"],
|
|
32
|
+
allowedJurisdictions: ["MX", "US"]
|
|
33
|
+
};
|
|
34
|
+
(0, vitest_1.it)("should choose standard token standard below threshold", () => {
|
|
35
|
+
const evalRes = policyEngine.evaluate({ amount: 3000, assetCode: "USDC", jurisdiction: "MX", isAccredited: true }, rules);
|
|
36
|
+
(0, vitest_1.expect)(evalRes.allowed).toBe(true);
|
|
37
|
+
(0, vitest_1.expect)(evalRes.tokenType).toBe("standard");
|
|
38
|
+
});
|
|
39
|
+
(0, vitest_1.it)("should choose confidential token standard above threshold", () => {
|
|
40
|
+
const evalRes = policyEngine.evaluate({ amount: 12000, assetCode: "USDC", jurisdiction: "MX", isAccredited: true }, rules);
|
|
41
|
+
(0, vitest_1.expect)(evalRes.allowed).toBe(true);
|
|
42
|
+
(0, vitest_1.expect)(evalRes.tokenType).toBe("confidential");
|
|
43
|
+
(0, vitest_1.expect)(evalRes.requiredProofs).toContain("zkBalance");
|
|
44
|
+
});
|
|
45
|
+
(0, vitest_1.it)("should block transacting in unauthorized jurisdictions", () => {
|
|
46
|
+
const evalRes = policyEngine.evaluate({ amount: 2000, assetCode: "USDC", jurisdiction: "CA" }, rules);
|
|
47
|
+
(0, vitest_1.expect)(evalRes.allowed).toBe(false);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
//# sourceMappingURL=sdk.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk.test.js","sourceRoot":"","sources":["../../../src/sdk.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SEP-10 Web Authentication types and client helpers for Confidia SDK.
|
|
3
|
+
* These types are shared between the frontend (wallet-kit, auth.ts) and backend (server.ts).
|
|
4
|
+
*/
|
|
5
|
+
export interface Sep10Challenge {
|
|
6
|
+
/** Base64-encoded XDR of the unsigned challenge transaction */
|
|
7
|
+
transaction: string;
|
|
8
|
+
/** Stellar network passphrase the transaction was built for */
|
|
9
|
+
network_passphrase: string;
|
|
10
|
+
}
|
|
11
|
+
export interface Sep10VerifyRequest {
|
|
12
|
+
/** Signed XDR envelope returned by the wallet */
|
|
13
|
+
transaction: string;
|
|
14
|
+
}
|
|
15
|
+
export interface Sep10Session {
|
|
16
|
+
/** JWT token issued after successful SEP-10 challenge verification */
|
|
17
|
+
token: string;
|
|
18
|
+
/** Stellar G-address of the authenticated account */
|
|
19
|
+
address: string;
|
|
20
|
+
/** Unix timestamp when the session expires */
|
|
21
|
+
expiresAt: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Fetches a SEP-10 challenge for the given Stellar address from a Confidia API endpoint.
|
|
25
|
+
*/
|
|
26
|
+
export declare function fetchSep10Challenge(apiBase: string, address: string): Promise<Sep10Challenge>;
|
|
27
|
+
/**
|
|
28
|
+
* Submits a signed SEP-10 challenge transaction to receive a session JWT.
|
|
29
|
+
*/
|
|
30
|
+
export declare function verifySep10Signature(apiBase: string, signedXdr: string): Promise<Sep10Session>;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* SEP-10 Web Authentication types and client helpers for Confidia SDK.
|
|
4
|
+
* These types are shared between the frontend (wallet-kit, auth.ts) and backend (server.ts).
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.fetchSep10Challenge = fetchSep10Challenge;
|
|
8
|
+
exports.verifySep10Signature = verifySep10Signature;
|
|
9
|
+
/**
|
|
10
|
+
* Fetches a SEP-10 challenge for the given Stellar address from a Confidia API endpoint.
|
|
11
|
+
*/
|
|
12
|
+
async function fetchSep10Challenge(apiBase, address) {
|
|
13
|
+
const res = await fetch(`${apiBase}/auth/challenge?address=${address}`);
|
|
14
|
+
const text = await res.text();
|
|
15
|
+
try {
|
|
16
|
+
const data = JSON.parse(text);
|
|
17
|
+
if (data.error)
|
|
18
|
+
throw new Error(data.error);
|
|
19
|
+
return data;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
throw new Error(`SEP-10 challenge endpoint returned non-JSON (status ${res.status}). Is the API running?`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Submits a signed SEP-10 challenge transaction to receive a session JWT.
|
|
27
|
+
*/
|
|
28
|
+
async function verifySep10Signature(apiBase, signedXdr) {
|
|
29
|
+
const res = await fetch(`${apiBase}/auth/verify`, {
|
|
30
|
+
method: "POST",
|
|
31
|
+
headers: { "Content-Type": "application/json" },
|
|
32
|
+
body: JSON.stringify({ transaction: signedXdr })
|
|
33
|
+
});
|
|
34
|
+
const text = await res.text();
|
|
35
|
+
try {
|
|
36
|
+
const data = JSON.parse(text);
|
|
37
|
+
if (data.error)
|
|
38
|
+
throw new Error(data.error);
|
|
39
|
+
return {
|
|
40
|
+
token: data.token,
|
|
41
|
+
address: data.address || "",
|
|
42
|
+
expiresAt: Math.floor(Date.now() / 1000) + 3600
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
throw new Error(`SEP-10 verify endpoint returned non-JSON (status ${res.status}). Is the API running?`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=sep10.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sep10.js","sourceRoot":"","sources":["../../../src/sep10.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AA0BH,kDAeC;AAKD,oDAuBC;AA9CD;;GAEG;AACI,KAAK,UAAU,mBAAmB,CACvC,OAAe,EACf,OAAe;IAEf,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,2BAA2B,OAAO,EAAE,CAAC,CAAC;IACxE,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5C,OAAO,IAAsB,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,uDAAuD,GAAG,CAAC,MAAM,wBAAwB,CAC1F,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,oBAAoB,CACxC,OAAe,EACf,SAAiB;IAEjB,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,cAAc,EAAE;QAChD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,SAAS,EAA+B,CAAC;KAC9E,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5C,OAAO;YACL,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,EAAE;YAC3B,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI;SAChD,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,oDAAoD,GAAG,CAAC,MAAM,wBAAwB,CACvF,CAAC;IACJ,CAAC;AACH,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "confidia-sdk",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Legal Context Protocol (LCP) client and compliance policy engine for private, compliant tokenized-dollar distribution on Stellar.",
|
|
5
|
+
"keywords": ["stellar", "soroban", "compliance", "legal-context-protocol", "sep-10"],
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "Confidia",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/Eras256/Confidia.git",
|
|
11
|
+
"directory": "packages/confidia-sdk"
|
|
12
|
+
},
|
|
13
|
+
"homepage": "https://github.com/Eras256/Confidia#readme",
|
|
14
|
+
"main": "./dist/cjs/src/index.js",
|
|
15
|
+
"module": "./dist/esm/src/index.js",
|
|
16
|
+
"types": "./dist/esm/src/index.d.ts",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./dist/esm/src/index.d.ts",
|
|
20
|
+
"import": "./dist/esm/src/index.js",
|
|
21
|
+
"require": "./dist/cjs/src/index.js"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist/esm/src",
|
|
26
|
+
"dist/cjs/src",
|
|
27
|
+
"README.md"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsc -p tsconfig.esm.json && tsc -p tsconfig.cjs.json",
|
|
31
|
+
"test": "vitest run"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"typescript": "^5.4.5",
|
|
35
|
+
"vitest": "^1.6.0"
|
|
36
|
+
}
|
|
37
|
+
}
|