@uvrn/adapter 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.
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ /**
3
+ * DRVC3 Wrapper Tests
4
+ * Tests the wrapInDRVC3 function and schema validation
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const ethers_1 = require("ethers");
8
+ const wrapper_1 = require("../src/wrapper");
9
+ const validator_1 = require("../src/validator");
10
+ const signer_1 = require("../src/signer");
11
+ describe('DRVC3 Wrapper', () => {
12
+ // Mock DeltaReceipt (as would come from Layer 1)
13
+ const mockDeltaReceipt = {
14
+ bundleId: 'test-bundle-001',
15
+ deltaFinal: 0.05,
16
+ sources: ['Source A', 'Source B'],
17
+ rounds: [
18
+ {
19
+ round: 1,
20
+ deltasByMetric: { revenue: 0.05, users: 0.0 },
21
+ withinThreshold: true,
22
+ witnessRequired: false
23
+ }
24
+ ],
25
+ suggestedFixes: [],
26
+ outcome: 'consensus',
27
+ hash: 'a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2'
28
+ };
29
+ let testWallet;
30
+ beforeAll(() => {
31
+ // Create a deterministic wallet for testing
32
+ testWallet = ethers_1.Wallet.createRandom();
33
+ });
34
+ it('should wrap DeltaReceipt in valid DRVC3 envelope', async () => {
35
+ const drvc3 = await (0, wrapper_1.wrapInDRVC3)(mockDeltaReceipt, testWallet, {
36
+ issuer: 'uvrn-test',
37
+ event: 'delta-reconciliation'
38
+ });
39
+ // Check required fields
40
+ expect(drvc3.receipt_id).toMatch(/^drvc3-test-bundle-001-\d+$/);
41
+ expect(drvc3.issuer).toBe('uvrn-test');
42
+ expect(drvc3.event).toBe('delta-reconciliation');
43
+ expect(drvc3.timestamp).toBeDefined();
44
+ expect(drvc3.block_state).toBe('loose');
45
+ expect(drvc3.certificate).toBe('DRVC3 v1.0');
46
+ // Check integrity block
47
+ expect(drvc3.integrity.hash_algorithm).toBe('sha256');
48
+ expect(drvc3.integrity.hash).toBe(mockDeltaReceipt.hash);
49
+ expect(drvc3.integrity.signature_method).toBe('eip191');
50
+ expect(drvc3.integrity.signature).toBeDefined();
51
+ expect(drvc3.integrity.signer_address).toBe(testWallet.address);
52
+ // Check validation block
53
+ expect(drvc3.validation.v_score).toBe(mockDeltaReceipt.deltaFinal);
54
+ expect(drvc3.validation.checks.delta_receipt).toEqual(mockDeltaReceipt);
55
+ });
56
+ it('should produce schema-valid DRVC3 receipt', async () => {
57
+ const drvc3 = await (0, wrapper_1.wrapInDRVC3)(mockDeltaReceipt, testWallet, {
58
+ issuer: 'uvrn',
59
+ event: 'test'
60
+ });
61
+ const result = (0, validator_1.validateDRVC3)(drvc3);
62
+ expect(result.valid).toBe(true);
63
+ expect(result.errors).toBeUndefined();
64
+ });
65
+ it('should include optional fields when provided', async () => {
66
+ const drvc3 = await (0, wrapper_1.wrapInDRVC3)(mockDeltaReceipt, testWallet, {
67
+ issuer: 'uvrn',
68
+ event: 'delta-reconciliation',
69
+ blockState: 'blocked',
70
+ certificate: 'DRVC3 v1.1',
71
+ description: 'Test receipt',
72
+ tags: ['#uvrn', '#receipt', '#test']
73
+ });
74
+ expect(drvc3.block_state).toBe('blocked');
75
+ expect(drvc3.certificate).toBe('DRVC3 v1.1');
76
+ expect(drvc3.description).toBe('Test receipt');
77
+ expect(drvc3.tags).toEqual(['#uvrn', '#receipt', '#test']);
78
+ });
79
+ it('should create verifiable signature', async () => {
80
+ const drvc3 = await (0, wrapper_1.wrapInDRVC3)(mockDeltaReceipt, testWallet, {
81
+ issuer: 'uvrn',
82
+ event: 'test'
83
+ });
84
+ // Recover signer from signature
85
+ const recoveredAddress = (0, signer_1.recoverSigner)(drvc3.integrity.hash, drvc3.integrity.signature);
86
+ expect(recoveredAddress.toLowerCase()).toBe(testWallet.address.toLowerCase());
87
+ });
88
+ it('should extract original DeltaReceipt from envelope', async () => {
89
+ const drvc3 = await (0, wrapper_1.wrapInDRVC3)(mockDeltaReceipt, testWallet, {
90
+ issuer: 'uvrn',
91
+ event: 'test'
92
+ });
93
+ const extracted = (0, wrapper_1.extractDeltaReceipt)(drvc3);
94
+ expect(extracted).toEqual(mockDeltaReceipt);
95
+ });
96
+ });
package/jest.config.js ADDED
@@ -0,0 +1,12 @@
1
+ /** @type {import('ts-jest').JestConfigWithTsJest} */
2
+ module.exports = {
3
+ preset: 'ts-jest',
4
+ testEnvironment: 'node',
5
+ testMatch: ['**/tests/**/*.test.ts'],
6
+ moduleFileExtensions: ['ts', 'js', 'json'],
7
+ collectCoverageFrom: ['src/**/*.ts'],
8
+ moduleNameMapper: {
9
+ '^@uvrn/core$': '<rootDir>/../uvrn-core/src'
10
+ }
11
+ };
12
+
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@uvrn/adapter",
3
+ "version": "1.0.0",
4
+ "description": "UVRN DRVC3 envelope adapter — wraps core receipts with EIP-191 signatures",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "keywords": [
8
+ "uvrn",
9
+ "drvc3",
10
+ "eip191",
11
+ "receipts"
12
+ ],
13
+ "license": "MIT",
14
+ "dependencies": {
15
+ "ethers": "^6.0.0",
16
+ "ajv": "^8.12.0",
17
+ "ajv-formats": "^2.1.1",
18
+ "@uvrn/core": "1.0.0"
19
+ },
20
+ "devDependencies": {
21
+ "@types/jest": "^29.5.0",
22
+ "@types/node": "^20.0.0",
23
+ "jest": "^29.5.0",
24
+ "ts-jest": "^29.1.0",
25
+ "typescript": "^5.3.0"
26
+ },
27
+ "engines": {
28
+ "node": ">=18.0.0"
29
+ },
30
+ "scripts": {
31
+ "build": "tsc",
32
+ "test": "jest",
33
+ "lint": "eslint src/**/*.ts",
34
+ "clean": "rm -rf dist"
35
+ }
36
+ }
@@ -0,0 +1,115 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://uvrn.org/schemas/drvc3.v1.01.json",
4
+ "title": "DRVC3 Receipt v1.01",
5
+ "description": "DRVC3 envelope with Layer 2 extensions support. Backward-compatible with v1.0.",
6
+ "type": "object",
7
+ "required": [
8
+ "receipt_id",
9
+ "issuer",
10
+ "event",
11
+ "timestamp",
12
+ "integrity",
13
+ "block_state",
14
+ "certificate"
15
+ ],
16
+ "properties": {
17
+ "receipt_id": {
18
+ "type": "string"
19
+ },
20
+ "issuer": {
21
+ "type": "string"
22
+ },
23
+ "event": {
24
+ "type": "string"
25
+ },
26
+ "timestamp": {
27
+ "type": "string",
28
+ "format": "date-time"
29
+ },
30
+ "description": {
31
+ "type": "string"
32
+ },
33
+ "resource": {
34
+ "type": "object",
35
+ "properties": {
36
+ "type": {
37
+ "type": "string"
38
+ },
39
+ "url": {
40
+ "type": "string"
41
+ },
42
+ "branch": {
43
+ "type": "string"
44
+ },
45
+ "commit_hash": {
46
+ "type": "string"
47
+ }
48
+ }
49
+ },
50
+ "integrity": {
51
+ "type": "object",
52
+ "required": [
53
+ "hash_algorithm",
54
+ "hash",
55
+ "signature_method",
56
+ "signature",
57
+ "signer_address"
58
+ ],
59
+ "properties": {
60
+ "hash_algorithm": {
61
+ "enum": [
62
+ "sha256"
63
+ ]
64
+ },
65
+ "hash": {
66
+ "type": "string"
67
+ },
68
+ "signature_method": {
69
+ "enum": [
70
+ "eip191"
71
+ ]
72
+ },
73
+ "signature": {
74
+ "type": "string"
75
+ },
76
+ "signer_address": {
77
+ "type": "string"
78
+ }
79
+ }
80
+ },
81
+ "validation": {
82
+ "type": "object",
83
+ "properties": {
84
+ "v_score": {
85
+ "type": "number"
86
+ },
87
+ "checks": {
88
+ "type": "object"
89
+ }
90
+ }
91
+ },
92
+ "block_state": {
93
+ "enum": [
94
+ "loose",
95
+ "blocked"
96
+ ]
97
+ },
98
+ "certificate": {
99
+ "type": "string"
100
+ },
101
+ "replay_instructions": {
102
+ "type": "object"
103
+ },
104
+ "tags": {
105
+ "type": "array",
106
+ "items": {
107
+ "type": "string"
108
+ }
109
+ },
110
+ "extensions": {
111
+ "type": "object",
112
+ "description": "Layer 2 provenance data — source URLs, timestamps, evidence links, domain metadata. Not covered by L1 integrity hash."
113
+ }
114
+ }
115
+ }
package/src/index.ts ADDED
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Loosechain UVRN Adapter
3
+ * Layer 2 - Wraps Delta Engine Core receipts in DRVC3 envelopes
4
+ */
5
+
6
+ // Types
7
+ export * from './types';
8
+
9
+ // Core wrapper
10
+ export { wrapInDRVC3, extractDeltaReceipt } from './wrapper';
11
+
12
+ // Signing utilities
13
+ export { signHash, recoverSigner, verifySignature } from './signer';
14
+
15
+ // Validation
16
+ export { validateDRVC3, isDRVC3Receipt } from './validator';
package/src/signer.ts ADDED
@@ -0,0 +1,47 @@
1
+ /**
2
+ * EIP-191 Signing Utilities
3
+ * Provides Ethereum personal message signing for DRVC3 receipts
4
+ */
5
+
6
+ import { Wallet, HDNodeWallet, verifyMessage } from 'ethers';
7
+
8
+ /**
9
+ * Signs a hash using EIP-191 (Ethereum Signed Message)
10
+ * @param hash - The hex string hash to sign
11
+ * @param wallet - ethers Wallet instance with private key
12
+ * @returns Promise resolving to the signature hex string
13
+ */
14
+ export async function signHash(hash: string, wallet: Wallet | HDNodeWallet): Promise<string> {
15
+ // signMessage automatically prefixes with "\x19Ethereum Signed Message:\n" + message length
16
+ return wallet.signMessage(hash);
17
+ }
18
+
19
+ /**
20
+ * Recovers the signer address from a hash and signature
21
+ * @param hash - The original hash that was signed
22
+ * @param signature - The EIP-191 signature
23
+ * @returns The signer's Ethereum address
24
+ */
25
+ export function recoverSigner(hash: string, signature: string): string {
26
+ return verifyMessage(hash, signature);
27
+ }
28
+
29
+ /**
30
+ * Verifies that a signature was created by the expected signer
31
+ * @param hash - The original hash that was signed
32
+ * @param signature - The EIP-191 signature
33
+ * @param expectedAddress - The expected signer address
34
+ * @returns True if the signature is valid and matches the expected address
35
+ */
36
+ export function verifySignature(
37
+ hash: string,
38
+ signature: string,
39
+ expectedAddress: string
40
+ ): boolean {
41
+ try {
42
+ const recoveredAddress = recoverSigner(hash, signature);
43
+ return recoveredAddress.toLowerCase() === expectedAddress.toLowerCase();
44
+ } catch {
45
+ return false;
46
+ }
47
+ }
package/src/types.ts ADDED
@@ -0,0 +1,102 @@
1
+ /**
2
+ * DRVC3 Types for UVRN Adapter (v1.01)
3
+ * Layer 2 envelope types that wrap Layer 1 DeltaReceipt
4
+ *
5
+ * v1.01 adds the `extensions` field for Layer 2 provenance data.
6
+ */
7
+
8
+ import { DeltaReceipt } from '@uvrn/core';
9
+
10
+ /**
11
+ * DRVC3 Integrity block - contains hash and signature data
12
+ */
13
+ export interface DRVC3Integrity {
14
+ hash_algorithm: 'sha256';
15
+ hash: string;
16
+ signature_method: 'eip191';
17
+ signature: string;
18
+ signer_address: string;
19
+ }
20
+
21
+ /**
22
+ * DRVC3 Validation block - contains score and embedded checks
23
+ */
24
+ export interface DRVC3Validation {
25
+ v_score: number;
26
+ checks: {
27
+ delta_receipt: DeltaReceipt;
28
+ [key: string]: unknown;
29
+ };
30
+ }
31
+
32
+ /**
33
+ * DRVC3 Resource block (optional) - describes the verified resource
34
+ */
35
+ export interface DRVC3Resource {
36
+ type?: string;
37
+ url?: string;
38
+ branch?: string;
39
+ commit_hash?: string;
40
+ }
41
+
42
+ /**
43
+ * Block state - "loose" means mutable/portable, "blocked" means canonized/permanent
44
+ */
45
+ export type BlockState = 'loose' | 'blocked';
46
+
47
+ /**
48
+ * Full DRVC3 Receipt Envelope
49
+ * Wraps Layer 1 DeltaReceipt with protocol metadata and signatures
50
+ */
51
+ export interface DRVC3Receipt {
52
+ receipt_id: string;
53
+ issuer: string;
54
+ event: string;
55
+ timestamp: string;
56
+ description?: string;
57
+ resource?: DRVC3Resource;
58
+ integrity: DRVC3Integrity;
59
+ validation: DRVC3Validation;
60
+ block_state: BlockState;
61
+ certificate: string;
62
+ replay_instructions?: Record<string, unknown>;
63
+ tags?: string[];
64
+ /**
65
+ * Layer 2 extension data — provenance, evidence, domain-specific metadata.
66
+ * This field is NOT covered by the L1 integrity hash. It is envelope metadata
67
+ * owned by the consumer chain (e.g., MarketChain source URLs, evidence links).
68
+ */
69
+ extensions?: Record<string, unknown>;
70
+ }
71
+
72
+ /**
73
+ * Options for wrapping a DeltaReceipt in DRVC3 envelope
74
+ */
75
+ export interface WrapOptions {
76
+ /** Issuer identifier (e.g., "uvrn", "app.example.com") */
77
+ issuer: string;
78
+ /** Event type (e.g., "delta-reconciliation") */
79
+ event: string;
80
+ /** Block state - defaults to "loose" */
81
+ blockState?: BlockState;
82
+ /** DRVC3 certificate version - defaults to "DRVC3 v1.0" */
83
+ certificate?: string;
84
+ /** Optional description */
85
+ description?: string;
86
+ /** Optional resource metadata */
87
+ resource?: DRVC3Resource;
88
+ /** Optional replay instructions */
89
+ replayInstructions?: Record<string, unknown>;
90
+ /** Optional tags (e.g., ["#uvrn", "#receipt"]) */
91
+ tags?: string[];
92
+ /** Optional Layer 2 extension data (provenance, evidence, domain metadata) */
93
+ extensions?: Record<string, unknown>;
94
+ }
95
+
96
+ /**
97
+ * Validation result from schema validation
98
+ */
99
+ export interface DRVC3ValidationResult {
100
+ valid: boolean;
101
+ errors?: string[];
102
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * DRVC3 Schema Validator
3
+ * Uses ajv to validate DRVC3 receipts against the official schema
4
+ */
5
+
6
+ import Ajv from 'ajv';
7
+ import * as path from 'path';
8
+ import * as fs from 'fs';
9
+ import { DRVC3ValidationResult } from './types';
10
+
11
+ // Load schema from file
12
+ const schemaPath = path.join(__dirname, '../schemas/drvc3.schema.json');
13
+ const drvc3Schema = JSON.parse(fs.readFileSync(schemaPath, 'utf-8'));
14
+
15
+ // Initialize Ajv with JSON Schema 2020-12 support
16
+ const ajv = new Ajv({ strict: false });
17
+
18
+ // Add formats support (date-time, etc.)
19
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
20
+ const addFormats = require('ajv-formats');
21
+ addFormats(ajv);
22
+
23
+ // Compile the schema once
24
+ const validateSchema = ajv.compile(drvc3Schema);
25
+
26
+ /**
27
+ * Validates a DRVC3 receipt against the official schema
28
+ * @param receipt - The receipt object to validate
29
+ * @returns Validation result with errors if invalid
30
+ */
31
+ export function validateDRVC3(receipt: unknown): DRVC3ValidationResult {
32
+ const valid = validateSchema(receipt);
33
+
34
+ if (valid) {
35
+ return { valid: true };
36
+ }
37
+
38
+ const errors = validateSchema.errors?.map(err => {
39
+ const path = err.instancePath || '/';
40
+ return `${path}: ${err.message}`;
41
+ }) || ['Unknown validation error'];
42
+
43
+ return { valid: false, errors };
44
+ }
45
+
46
+ /**
47
+ * Type guard to check if an object is a valid DRVC3 receipt
48
+ * @param obj - Object to check
49
+ * @returns True if the object is a valid DRVC3 receipt
50
+ */
51
+ export function isDRVC3Receipt(obj: unknown): boolean {
52
+ return validateDRVC3(obj).valid;
53
+ }
package/src/wrapper.ts ADDED
@@ -0,0 +1,103 @@
1
+ /**
2
+ * DRVC3 Wrapper
3
+ * Wraps Layer 1 DeltaReceipt in a DRVC3 envelope with EIP-191 signatures
4
+ *
5
+ * Key Principle: The DeltaReceipt hash is READ-ONLY from Layer 1.
6
+ * DRVC3 envelope fields (receipt_id, timestamp, signature) are envelope metadata
7
+ * and do NOT affect determinism or replay.
8
+ */
9
+
10
+ import { DeltaReceipt } from '@uvrn/core';
11
+ import { Wallet, HDNodeWallet, Signer } from 'ethers';
12
+ import { DRVC3Receipt, WrapOptions } from './types';
13
+ import { signHash } from './signer';
14
+
15
+ /**
16
+ * Wraps a DeltaReceipt in a DRVC3 envelope
17
+ *
18
+ * @param deltaReceipt - Layer 1 DeltaReceipt (deterministic, hash-covered)
19
+ * @param signer - ethers Wallet for EIP-191 signing
20
+ * @param options - Envelope options (issuer, event, etc.)
21
+ * @returns Promise resolving to complete DRVC3 receipt
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * import { runDeltaEngine } from '@uvrn/core';
26
+ * import { wrapInDRVC3 } from '@uvrn/adapter';
27
+ * import { Wallet } from 'ethers';
28
+ *
29
+ * const deltaReceipt = runDeltaEngine(bundle);
30
+ * const wallet = new Wallet(privateKey);
31
+ * const drvc3 = await wrapInDRVC3(deltaReceipt, wallet, {
32
+ * issuer: 'uvrn',
33
+ * event: 'delta-reconciliation'
34
+ * });
35
+ * ```
36
+ */
37
+ export async function wrapInDRVC3(
38
+ deltaReceipt: DeltaReceipt,
39
+ signer: Wallet | HDNodeWallet,
40
+ options: WrapOptions
41
+ ): Promise<DRVC3Receipt> {
42
+ // 1. Generate receipt_id (ENVELOPE METADATA - non-deterministic, intentional)
43
+ const timestamp = new Date().toISOString();
44
+ const receipt_id = `drvc3-${deltaReceipt.bundleId}-${Date.now()}`;
45
+
46
+ // 2. Read hash from DeltaReceipt (HASH DOMAIN - read-only from Layer 1)
47
+ const hash = deltaReceipt.hash;
48
+
49
+ // 3. Sign hash with EIP-191 (ENVELOPE METADATA - certifies "who" and "when")
50
+ const signature = await signHash(hash, signer);
51
+
52
+ // 4. Construct DRVC3 envelope
53
+ const drvc3: DRVC3Receipt = {
54
+ receipt_id,
55
+ issuer: options.issuer,
56
+ event: options.event,
57
+ timestamp,
58
+ integrity: {
59
+ hash_algorithm: 'sha256',
60
+ hash,
61
+ signature_method: 'eip191',
62
+ signature,
63
+ signer_address: signer.address
64
+ },
65
+ validation: {
66
+ v_score: deltaReceipt.deltaFinal,
67
+ checks: {
68
+ delta_receipt: deltaReceipt
69
+ }
70
+ },
71
+ block_state: options.blockState || 'loose',
72
+ certificate: options.certificate || 'DRVC3 v1.01'
73
+ };
74
+
75
+ // Add optional fields if provided
76
+ if (options.description) {
77
+ drvc3.description = options.description;
78
+ }
79
+ if (options.resource) {
80
+ drvc3.resource = options.resource;
81
+ }
82
+ if (options.replayInstructions) {
83
+ drvc3.replay_instructions = options.replayInstructions;
84
+ }
85
+ if (options.extensions) {
86
+ drvc3.extensions = options.extensions;
87
+ }
88
+ if (options.tags) {
89
+ drvc3.tags = options.tags;
90
+ }
91
+
92
+ return drvc3;
93
+ }
94
+
95
+ /**
96
+ * Extracts the original DeltaReceipt from a DRVC3 envelope
97
+ *
98
+ * @param drvc3 - DRVC3 receipt envelope
99
+ * @returns The embedded DeltaReceipt
100
+ */
101
+ export function extractDeltaReceipt(drvc3: DRVC3Receipt): DeltaReceipt {
102
+ return drvc3.validation.checks.delta_receipt;
103
+ }