valr-typescript-client 1.0.9 → 1.0.10

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/CHECKSUMS.txt ADDED
@@ -0,0 +1,50 @@
1
+ # Package Checksums
2
+
3
+ Generated on: 2025-12-30 14:57:51 UTC
4
+ Git commit: 3e9dd020502b07c1e87bb03cd1c06540efde3ebd
5
+ Version: 1.0.10
6
+
7
+ ## Distribution Files (SHA256)
8
+
9
+ 06158769642deabfe17ffb66d8fd2b6d5153bba63e45201a5457d171d8c31497 dist/index.js
10
+ 26bfc380548882a1ea5da2b993de618c5566cfc4b6442d8bc67a9a7f25bb1ed7 dist/index.js.map
11
+ 69ce37acf0ed6a37333e46eb7e86499e4509eb7d3c2279993a05d1c1fd640cfd dist/index.d.mts
12
+ 69ce37acf0ed6a37333e46eb7e86499e4509eb7d3c2279993a05d1c1fd640cfd dist/index.d.ts
13
+ 9f55f3468cc5c0aa57580e7bbb95b5cae9f5e60982428e90a844aba79d0872af dist/index.mjs
14
+ c10a93a7b2361bef6672805183ab08595fc948e3bf205d7ca8b5052620f3e226 dist/index.mjs.map
15
+
16
+ ## Source Files (SHA256)
17
+
18
+ 05cf6e982fcbd24cebc6c1b4c6e366095859cdf503eb70f5faf4d9bb9844631a src/client/ValrClient.ts
19
+ 0705454404aa0e0f2ce619615600d871c8052ac0afe495bb412219d9a6c032ac src/types/public.ts
20
+ 0a9bed00d1ee34300d532c01c86a300d76f51b96d50aea2ebae15750c7c06d94 src/api/account.ts
21
+ 0b4530d458e0c3bbadb79566943ef466404215e545f25c4965c72d9bfeee86dc src/api/health.ts
22
+ 15ef50a824d04e4466a4e34c29b54429c4d36e64d15eed1374c7165452da3abf src/api/loans.ts
23
+ 174ffc46347008d3f473af1916e8b1b38fb9752e68a69776df831dca676a1342 src/api/public.ts
24
+ 392124cca58a1532bd57472ba574bc065052c552ea8f10b7c675c942310c67e8 src/api/wallets.ts
25
+ 39fd4908c74bcca8c4e74a3a4e16de4439dfca781a7644ca9383c5f5096744cf src/types/futures.ts
26
+ 3ff881e0a329681fecb0eae9ce178e9d1e6e4d6a6d55bfb5eec99a46c85d4e2a src/types/margin.ts
27
+ 40f2245b2685e634bd0f531367561c1c26d174cc083c496c1f914e8c6a9f948a src/client/ValrWebSocketClient.ts
28
+ 4202fe777fda3e43ff944971783116f17031d124395e4a44cb2bf2bec5ff246c src/types/bundles.ts
29
+ 43ce3b42153a2e1a2d290ea893507c820e4461eb2162b1ccfa0d832118468618 src/api/margin.ts
30
+ 4abf3aa146557f6f33f039a03a675cb6588da94f29e885ef97458cb698699425 src/types/common.ts
31
+ 4b598e192fe1571f36138724f67d49f645d1b4c90cc527fe0e6901d5f950372c src/auth/RequestSigner.ts
32
+ 5475e829a33f944dec5dd4079066aa621c76c7767ac56f172a322ce110d43f0b src/types/pay.ts
33
+ 551aa287e635dad4d0209502a0410f09c169715a5bac95366a875038c3e50504 src/api/futures.ts
34
+ 5572db3151cd4db275a7ac6e8a8859e3c9048e0bd873a113f445139c0db2017c src/api/bundles.ts
35
+ 562187bbc4b29a68add1fad7d63c73fb1345b45154358fa0276e2e224cfb7e5a src/types/account.ts
36
+ 58186035ea5e98178c3a9b2b0404d0b0f57765b074af92289e0f9cfaa7acfcfe src/utils/http.ts
37
+ 593e9b1515cb7e1316feae0cf24a9300b879284677c5e790e650502b32c70706 src/types/websocket.ts
38
+ 612b1e543d1bbd97b75e814fa7d9b4ff4b1786f6b3671a03019917049e38a96e src/types/stake.ts
39
+ 6ec43e250aca38bc6a9dc4f16e5fe7e6ca25bd831270c5d02c1bc82d79f5731d src/types/loans.ts
40
+ 70636220daed500243e5cd40d25748efcd401a9ff50f4237fa200bce1fe3be38 src/errors/ValrError.ts
41
+ 81ced1343e19c4ea795981dc02f0a8163778b169463675498e508da2843a08e5 src/types/index.ts
42
+ 85b2242a529ed84d4e50b75fe9e8a393d4a53404734c8d9165a80bedc74887c4 src/types/trading.ts
43
+ a52c483def6de035f7fcf690b6102129ea22cb817bed5a106d3617c8edc7d849 src/api/stake.ts
44
+ c4c0979b4fc9a035bcf0d1bd8b379e5e2e85c8ea39a812cb7d8cd66ba5c04494 src/api/pay.ts
45
+ d8b3405cad342df23aeacaaacde277a4829028699a13bf0d129aea07beb23d68 src/api/trading.ts
46
+ ec209b0ff8de8e662c2ea701feccee22b53e6ed684affb3eacd39e68c3aa725a src/index.ts
47
+ f67a6c69ed003a1606221e792de802592aedb7164cafb7d7d2eab4fac105807a src/utils/constants.ts
48
+ f819d431730bb51a23d2cad32cc6eee83dc9d917e5cb9efd3201ffeb64d76ec5 src/client/AccountWebSocket.ts
49
+ fe3ced400781e287f691c1262b48ea5005d21b45f69172a8a03b470e14c63a6e src/client/TradeWebSocket.ts
50
+ fe8bec28add01e200bd95ad326a0511334671b3a82a3990d2ee521adca7a7a8e src/types/wallets.ts
package/README.md CHANGED
@@ -242,6 +242,112 @@ VALR API uses HMAC SHA512 signatures for authentication. This client handles all
242
242
  - Regularly rotate your API keys
243
243
  - Delete unused API keys
244
244
 
245
+ ## Package Integrity & Verification
246
+
247
+ This package includes cryptographic checksums to verify package integrity and protect against supply chain attacks.
248
+
249
+ ### Verifying Package Checksums
250
+
251
+ After installing from npm or any registry, you can verify the package integrity:
252
+
253
+ ```bash
254
+ # Using npm script (cross-platform)
255
+ npm run verify
256
+
257
+ # Or directly with Node.js
258
+ node node_modules/valr-typescript-client/scripts/verify-checksums.js
259
+
260
+ # Or on Unix systems with bash
261
+ bash node_modules/valr-typescript-client/scripts/verify-checksums.sh
262
+ ```
263
+
264
+ This will verify that:
265
+ - **All `dist/` files** (the compiled JavaScript you actually execute) match the official build
266
+ - The package hasn't been tampered with after publication
267
+ - You're running the exact code from the GitHub release
268
+ - Shows you the Git commit SHA of the source code it was built from
269
+
270
+ **What you're verifying:** The compiled JavaScript files in `dist/` are what run when you use this package. The checksums prove these match the official build from GitHub Actions.
271
+
272
+ ### What Gets Verified
273
+
274
+ The checksum verification checks:
275
+
276
+ **Distribution files (`dist/`)** - **What actually executes:**
277
+ - `dist/index.js`, `dist/index.mjs` - Compiled JavaScript (ESM/CJS)
278
+ - `dist/index.d.ts`, `dist/index.d.mts` - TypeScript definitions
279
+ - `dist/*.map` - Source maps
280
+
281
+ **Source files (`src/`)** - For transparency:
282
+ - Original TypeScript source code
283
+ - Allows you to inspect what the dist was built from
284
+ - Enables reproducible builds (advanced users)
285
+
286
+ **Metadata:**
287
+ - **Git commit SHA** - Links to exact source code on GitHub
288
+ - **Build timestamp** - When the package was built
289
+ - **Package version** - Version number
290
+
291
+ **Security model:** Checksums prove your `dist/` files match the official GitHub Actions build. You can inspect the source code at the Git commit shown in the checksums.
292
+
293
+ ### Building from Source
294
+
295
+ If you prefer to build from source yourself:
296
+
297
+ ```bash
298
+ # Clone the repository
299
+ git clone https://github.com/yashutanna/valr-typescript-client.git
300
+ cd valr-typescript-client
301
+
302
+ # Checkout a specific release
303
+ git checkout v1.0.9
304
+
305
+ # Install dependencies (use ci for reproducible builds)
306
+ npm ci
307
+
308
+ # Build
309
+ npm run build
310
+
311
+ # Run tests
312
+ npm test
313
+ ```
314
+
315
+ ### Reproducible Builds (Advanced)
316
+
317
+ For maximum trust, verify the official build was created from clean source code:
318
+
319
+ ```bash
320
+ # Clone and checkout the release
321
+ git clone https://github.com/yashutanna/valr-typescript-client.git
322
+ cd valr-typescript-client
323
+ git checkout v1.0.9
324
+
325
+ # Build from source
326
+ npm ci
327
+ npm run build
328
+
329
+ # Compare your build with official checksums
330
+ bash scripts/build-and-verify.sh
331
+ ```
332
+
333
+ This attempts to reproduce the official build and compares your locally-built `dist/` files with the checksums from the official release. Note that perfect reproducibility is challenging with JavaScript builds, but the script will show you any differences.
334
+
335
+ ### CI/CD Transparency
336
+
337
+ Every package published to npm includes:
338
+ - `CHECKSUMS.txt` - SHA256 hashes of all files
339
+ - Git commit SHA that was built
340
+ - Build timestamp
341
+ - Verification scripts
342
+
343
+ The checksums are available in multiple places:
344
+ - **In the repository** - Committed with each release (permanent Git history)
345
+ - **GitHub Releases** - Attached as an asset to every release
346
+ - **npm package** - Included at `node_modules/valr-typescript-client/CHECKSUMS.txt`
347
+ - **GitHub Actions** - Available as workflow artifacts
348
+
349
+ To verify a specific release, check the Git tag or GitHub release assets.
350
+
245
351
  ## Error Handling
246
352
 
247
353
  The client throws typed errors for different failure scenarios:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "valr-typescript-client",
3
- "version": "1.0.9",
3
+ "version": "1.0.10",
4
4
  "description": "TypeScript client for the VALR cryptocurrency exchange API with full type safety, WebSocket support, and comprehensive endpoint coverage",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -13,7 +13,11 @@
13
13
  }
14
14
  },
15
15
  "files": [
16
- "dist"
16
+ "dist",
17
+ "CHECKSUMS.txt",
18
+ "scripts/verify-checksums.js",
19
+ "scripts/verify-checksums.sh",
20
+ "scripts/build-and-verify.sh"
17
21
  ],
18
22
  "scripts": {
19
23
  "build": "tsup",
@@ -23,7 +27,8 @@
23
27
  "test:coverage": "vitest run --coverage",
24
28
  "type-check": "tsc --noEmit",
25
29
  "lint": "eslint src --ext .ts",
26
- "prepublishOnly": "npm run build && npm run test"
30
+ "prepublishOnly": "npm run build && npm run test",
31
+ "verify": "node scripts/verify-checksums.js"
27
32
  },
28
33
  "keywords": [
29
34
  "valr",
@@ -0,0 +1,91 @@
1
+ #!/bin/bash
2
+
3
+ # Reproducible Build & Verification Script
4
+ # Builds the package from source and compares with official checksums
5
+
6
+ set -e
7
+
8
+ echo "🔨 Building from source and verifying against official checksums..."
9
+ echo ""
10
+
11
+ # Check if CHECKSUMS.txt exists
12
+ if [ ! -f "CHECKSUMS.txt" ]; then
13
+ echo "❌ CHECKSUMS.txt not found!"
14
+ echo " Make sure you're in the package root directory."
15
+ exit 1
16
+ fi
17
+
18
+ # Extract expected commit and version
19
+ EXPECTED_COMMIT=$(grep "Git commit:" CHECKSUMS.txt | cut -d' ' -f3)
20
+ EXPECTED_VERSION=$(grep "Version:" CHECKSUMS.txt | cut -d' ' -f2)
21
+ CURRENT_COMMIT=$(git rev-parse HEAD)
22
+
23
+ echo "📦 Package version: $EXPECTED_VERSION"
24
+ echo "🔖 Official build commit: $EXPECTED_COMMIT"
25
+ echo "🔖 Current commit: $CURRENT_COMMIT"
26
+ echo ""
27
+
28
+ if [ "$EXPECTED_COMMIT" != "$CURRENT_COMMIT" ]; then
29
+ echo "⚠️ Warning: You're not on the official release commit!"
30
+ echo " Checking out $EXPECTED_COMMIT..."
31
+ git checkout "$EXPECTED_COMMIT"
32
+ fi
33
+
34
+ # Clean and build
35
+ echo "🧹 Cleaning previous build..."
36
+ rm -rf dist/
37
+
38
+ echo "📦 Installing dependencies..."
39
+ npm ci
40
+
41
+ echo "🔨 Building from source..."
42
+ npm run build
43
+
44
+ echo ""
45
+ echo "🔍 Comparing your build with official checksums..."
46
+ echo ""
47
+
48
+ FAILED=0
49
+ MATCHED=0
50
+
51
+ # Extract and verify dist file checksums
52
+ grep -A 1000 "## Distribution Files" CHECKSUMS.txt | \
53
+ grep -B 1000 "## Source Files" | \
54
+ grep "dist/" | \
55
+ while read -r expected_hash file; do
56
+ if [ -f "$file" ]; then
57
+ actual_hash=$(sha256sum "$file" | awk '{print $1}')
58
+ if [ "$expected_hash" = "$actual_hash" ]; then
59
+ echo " ✅ $file"
60
+ MATCHED=$((MATCHED + 1))
61
+ else
62
+ echo " ❌ $file (MISMATCH!)"
63
+ echo " Official: $expected_hash"
64
+ echo " Your build: $actual_hash"
65
+ FAILED=$((FAILED + 1))
66
+ fi
67
+ else
68
+ echo " ⚠️ $file (missing from your build)"
69
+ FAILED=$((FAILED + 1))
70
+ fi
71
+ done
72
+
73
+ echo ""
74
+
75
+ if [ $FAILED -eq 0 ]; then
76
+ echo "✅ SUCCESS: Your build matches the official build!"
77
+ echo " This proves the official package was built from this source code."
78
+ echo " The dist/ files you're running are legitimate."
79
+ else
80
+ echo "⚠️ REPRODUCIBILITY WARNING"
81
+ echo " Your build differs from the official build."
82
+ echo ""
83
+ echo " Possible reasons:"
84
+ echo " 1. Different Node.js version (use Node 24)"
85
+ echo " 2. Different dependency versions (use npm ci, not npm install)"
86
+ echo " 3. Different build environment (timestamps, paths, etc.)"
87
+ echo " 4. Build tools include timestamps or absolute paths"
88
+ echo ""
89
+ echo " Note: Some differences are expected with TypeScript/JavaScript builds."
90
+ echo " This doesn't necessarily mean the official build is malicious."
91
+ fi
@@ -0,0 +1,148 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Checksum Verification Script (Cross-platform Node.js version)
5
+ * Verifies the integrity of the installed package against CHECKSUMS.txt
6
+ */
7
+
8
+ const fs = require('fs');
9
+ const crypto = require('crypto');
10
+ const path = require('path');
11
+
12
+ const CHECKSUM_FILE = 'CHECKSUMS.txt';
13
+
14
+ function sha256File(filePath) {
15
+ const fileBuffer = fs.readFileSync(filePath);
16
+ const hashSum = crypto.createHash('sha256');
17
+ hashSum.update(fileBuffer);
18
+ return hashSum.digest('hex');
19
+ }
20
+
21
+ function parseChecksums(content) {
22
+ const lines = content.split('\n');
23
+ const checksums = { dist: [], src: [] };
24
+ let currentSection = null;
25
+
26
+ for (const line of lines) {
27
+ if (line.includes('## Distribution Files')) {
28
+ currentSection = 'dist';
29
+ } else if (line.includes('## Source Files')) {
30
+ currentSection = 'src';
31
+ } else if (currentSection && line.match(/^[a-f0-9]{64}\s+/)) {
32
+ const [hash, ...pathParts] = line.trim().split(/\s+/);
33
+ const filePath = pathParts.join(' ');
34
+ checksums[currentSection].push({ hash, path: filePath });
35
+ } else if (line.startsWith('Git commit:')) {
36
+ checksums.gitCommit = line.split(':')[1].trim();
37
+ } else if (line.startsWith('Version:')) {
38
+ checksums.version = line.split(':')[1].trim();
39
+ }
40
+ }
41
+
42
+ return checksums;
43
+ }
44
+
45
+ function main() {
46
+ console.log('🔍 Verifying package checksums...\n');
47
+
48
+ // Check if CHECKSUMS.txt exists
49
+ if (!fs.existsSync(CHECKSUM_FILE)) {
50
+ console.error('❌ CHECKSUMS.txt not found!');
51
+ console.error(' This package may not have been built with checksum verification.');
52
+ process.exit(1);
53
+ }
54
+
55
+ // Read and parse checksums
56
+ const checksumContent = fs.readFileSync(CHECKSUM_FILE, 'utf8');
57
+ const checksums = parseChecksums(checksumContent);
58
+
59
+ console.log(`📦 Package version: ${checksums.version}`);
60
+ console.log(`🔖 Git commit: ${checksums.gitCommit}`);
61
+ console.log('');
62
+
63
+ let failed = 0;
64
+ let verified = 0;
65
+ let missing = 0;
66
+
67
+ console.log('Verifying distribution files...');
68
+
69
+ // Verify dist files
70
+ for (const { hash: expectedHash, path: filePath } of checksums.dist) {
71
+ const normalizedPath = path.normalize(filePath);
72
+
73
+ if (fs.existsSync(normalizedPath)) {
74
+ const actualHash = sha256File(normalizedPath);
75
+ if (expectedHash === actualHash) {
76
+ console.log(` ✅ ${filePath}`);
77
+ verified++;
78
+ } else {
79
+ console.log(` ❌ ${filePath} (checksum mismatch!)`);
80
+ console.log(` Expected: ${expectedHash}`);
81
+ console.log(` Got: ${actualHash}`);
82
+ failed++;
83
+ }
84
+ } else {
85
+ console.log(` ⚠️ ${filePath} (file missing)`);
86
+ missing++;
87
+ }
88
+ }
89
+
90
+ console.log('');
91
+
92
+ // Check if we have source files (only in repo, not in npm package)
93
+ const hasSrcDir = fs.existsSync('src');
94
+ if (hasSrcDir && checksums.src && checksums.src.length > 0) {
95
+ console.log('Verifying source files...');
96
+
97
+ let srcVerified = 0;
98
+ let srcFailed = 0;
99
+ let srcMissing = 0;
100
+
101
+ for (const { hash: expectedHash, path: filePath } of checksums.src) {
102
+ const normalizedPath = path.normalize(filePath);
103
+
104
+ if (fs.existsSync(normalizedPath)) {
105
+ const actualHash = sha256File(normalizedPath);
106
+ if (expectedHash === actualHash) {
107
+ console.log(` ✅ ${filePath}`);
108
+ srcVerified++;
109
+ } else {
110
+ console.log(` ❌ ${filePath} (checksum mismatch!)`);
111
+ console.log(` Expected: ${expectedHash}`);
112
+ console.log(` Got: ${actualHash}`);
113
+ srcFailed++;
114
+ }
115
+ } else {
116
+ console.log(` ⚠️ ${filePath} (file missing)`);
117
+ srcMissing++;
118
+ }
119
+ }
120
+
121
+ verified += srcVerified;
122
+ failed += srcFailed;
123
+ missing += srcMissing;
124
+
125
+ console.log('');
126
+ }
127
+
128
+ console.log('');
129
+
130
+ if (failed === 0 && missing === 0) {
131
+ console.log('✅ All checksums verified successfully!');
132
+ console.log(` ${verified} file(s) verified`);
133
+ console.log(` This package matches the official build from commit ${checksums.gitCommit}`);
134
+ process.exit(0);
135
+ } else {
136
+ console.error('❌ Checksum verification failed!');
137
+ if (failed > 0) {
138
+ console.error(` ${failed} file(s) failed verification`);
139
+ }
140
+ if (missing > 0) {
141
+ console.error(` ${missing} file(s) missing`);
142
+ }
143
+ console.error(' This package may have been tampered with or corrupted.');
144
+ process.exit(1);
145
+ }
146
+ }
147
+
148
+ main();
@@ -0,0 +1,103 @@
1
+ #!/bin/bash
2
+
3
+ # Checksum Verification Script
4
+ # Verifies the integrity of the installed package against CHECKSUMS.txt
5
+
6
+ set -e
7
+
8
+ CHECKSUM_FILE="CHECKSUMS.txt"
9
+ VERIFIED=0
10
+ FAILED=0
11
+ MISSING=0
12
+
13
+ if [ ! -f "$CHECKSUM_FILE" ]; then
14
+ echo "❌ CHECKSUMS.txt not found!"
15
+ echo " This package may not have been built with checksum verification."
16
+ exit 1
17
+ fi
18
+
19
+ echo "🔍 Verifying package checksums..."
20
+ echo ""
21
+
22
+ # Extract git commit from checksums file
23
+ EXPECTED_COMMIT=$(grep "Git commit:" "$CHECKSUM_FILE" | cut -d' ' -f3)
24
+ PACKAGE_VERSION=$(grep "Version:" "$CHECKSUM_FILE" | cut -d' ' -f2)
25
+
26
+ echo "📦 Package version: $PACKAGE_VERSION"
27
+ echo "🔖 Git commit: $EXPECTED_COMMIT"
28
+ echo ""
29
+
30
+ # Verify distribution files
31
+ echo "Verifying distribution files..."
32
+
33
+ # Extract dist file checksums and verify
34
+ while IFS= read -r line; do
35
+ expected_hash=$(echo "$line" | awk '{print $1}')
36
+ file=$(echo "$line" | awk '{$1=""; print $0}' | sed 's/^ //')
37
+
38
+ if [ -f "$file" ]; then
39
+ actual_hash=$(sha256sum "$file" | awk '{print $1}')
40
+ if [ "$expected_hash" = "$actual_hash" ]; then
41
+ echo " ✅ $file"
42
+ VERIFIED=$((VERIFIED + 1))
43
+ else
44
+ echo " ❌ $file (checksum mismatch!)"
45
+ echo " Expected: $expected_hash"
46
+ echo " Got: $actual_hash"
47
+ FAILED=$((FAILED + 1))
48
+ fi
49
+ else
50
+ echo " ⚠️ $file (file missing)"
51
+ MISSING=$((MISSING + 1))
52
+ fi
53
+ done < <(grep -A 1000 "## Distribution Files" "$CHECKSUM_FILE" | grep -B 1000 "## Source Files" | grep "dist/")
54
+
55
+ echo ""
56
+
57
+ # Verify source files (if src directory exists)
58
+ if [ -d "src" ]; then
59
+ echo "Verifying source files..."
60
+
61
+ # Extract src file checksums and verify
62
+ while IFS= read -r line; do
63
+ expected_hash=$(echo "$line" | awk '{print $1}')
64
+ file=$(echo "$line" | awk '{$1=""; print $0}' | sed 's/^ //')
65
+
66
+ if [ -f "$file" ]; then
67
+ actual_hash=$(sha256sum "$file" | awk '{print $1}')
68
+ if [ "$expected_hash" = "$actual_hash" ]; then
69
+ echo " ✅ $file"
70
+ VERIFIED=$((VERIFIED + 1))
71
+ else
72
+ echo " ❌ $file (checksum mismatch!)"
73
+ echo " Expected: $expected_hash"
74
+ echo " Got: $actual_hash"
75
+ FAILED=$((FAILED + 1))
76
+ fi
77
+ else
78
+ echo " ⚠️ $file (file missing)"
79
+ MISSING=$((MISSING + 1))
80
+ fi
81
+ done < <(grep -A 1000 "## Source Files" "$CHECKSUM_FILE" | grep "src/")
82
+
83
+ echo ""
84
+ fi
85
+
86
+ echo ""
87
+
88
+ if [ $FAILED -eq 0 ] && [ $MISSING -eq 0 ]; then
89
+ echo "✅ All checksums verified successfully!"
90
+ echo " $VERIFIED file(s) verified"
91
+ echo " This package matches the official build from commit $EXPECTED_COMMIT"
92
+ exit 0
93
+ else
94
+ echo "❌ Checksum verification failed!"
95
+ if [ $FAILED -gt 0 ]; then
96
+ echo " $FAILED file(s) failed verification"
97
+ fi
98
+ if [ $MISSING -gt 0 ]; then
99
+ echo " $MISSING file(s) missing"
100
+ fi
101
+ echo " This package may have been tampered with or corrupted."
102
+ exit 1
103
+ fi