@pioneer-platform/pioneer-discovery 8.11.19 → 8.11.22

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pioneer-platform/pioneer-discovery",
3
- "version": "8.11.19",
3
+ "version": "8.11.22",
4
4
  "main": "./lib/index.js",
5
5
  "types": "./lib/main.d.ts",
6
6
  "_moduleAliases": {
@@ -0,0 +1,130 @@
1
+ #!/usr/bin/env bun
2
+ /*
3
+ * Analyze Icon Sources
4
+ * Check how many assets use keepkey.com vs keepkey.info
5
+ */
6
+
7
+ import assetData from '../src/generatedAssetData.json';
8
+
9
+ interface Asset {
10
+ symbol: string;
11
+ name: string;
12
+ chainId: string;
13
+ icon?: string;
14
+ assetId: string;
15
+ decimals: number;
16
+ isNative?: boolean;
17
+ }
18
+
19
+ async function checkIcon(url: string | undefined): Promise<boolean> {
20
+ if (!url) return false;
21
+ try {
22
+ const response = await fetch(url, { method: 'HEAD' });
23
+ return response.ok;
24
+ } catch (error) {
25
+ return false;
26
+ }
27
+ }
28
+
29
+ async function main() {
30
+ const entries = Object.entries(assetData as Record<string, Asset>);
31
+
32
+ const sources = {
33
+ keepkeyCom: [] as string[],
34
+ keepkeyInfo: [] as string[],
35
+ coingecko: [] as string[],
36
+ digitalocean: [] as string[],
37
+ other: [] as string[],
38
+ missing: [] as string[],
39
+ };
40
+
41
+ console.log('Analyzing icon sources...\n');
42
+
43
+ for (const [assetId, asset] of entries) {
44
+ if (!asset.icon) {
45
+ sources.missing.push(assetId);
46
+ } else if (asset.icon.includes('api.keepkey.com')) {
47
+ sources.keepkeyCom.push(assetId);
48
+ } else if (asset.icon.includes('api.keepkey.info')) {
49
+ sources.keepkeyInfo.push(assetId);
50
+ } else if (asset.icon.includes('coingecko.com')) {
51
+ sources.coingecko.push(assetId);
52
+ } else if (asset.icon.includes('digitaloceanspaces.com') || asset.icon.includes('keepkey.sfo3.cdn')) {
53
+ sources.digitalocean.push(assetId);
54
+ } else {
55
+ sources.other.push(assetId);
56
+ }
57
+ }
58
+
59
+ console.log('=== Icon Source Distribution ===');
60
+ console.log(`Total assets: ${entries.length}`);
61
+ console.log(`Missing icons: ${sources.missing.length}`);
62
+ console.log(`CoinGecko: ${sources.coingecko.length}`);
63
+ console.log(`KeepKey DigitalOcean: ${sources.digitalocean.length}`);
64
+ console.log(`api.keepkey.info: ${sources.keepkeyInfo.length}`);
65
+ console.log(`api.keepkey.com: ${sources.keepkeyCom.length} ⚠️`);
66
+ console.log(`Other sources: ${sources.other.length}`);
67
+ console.log('');
68
+
69
+ // Test samples
70
+ if (sources.keepkeyCom.length > 0) {
71
+ console.log('=== Testing api.keepkey.com URLs (Sample) ===');
72
+ const sample = sources.keepkeyCom.slice(0, 5);
73
+ for (const assetId of sample) {
74
+ const asset = assetData[assetId as keyof typeof assetData] as Asset;
75
+ const works = await checkIcon(asset.icon);
76
+ console.log(`${works ? '✅' : '❌'} ${asset.symbol} - ${asset.icon}`);
77
+ }
78
+ console.log('');
79
+ }
80
+
81
+ if (sources.keepkeyInfo.length > 0) {
82
+ console.log('=== Testing api.keepkey.info URLs (Sample) ===');
83
+ const sample = sources.keepkeyInfo.slice(0, 5);
84
+ for (const assetId of sample) {
85
+ const asset = assetData[assetId as keyof typeof assetData] as Asset;
86
+ const works = await checkIcon(asset.icon);
87
+ console.log(`${works ? '✅' : '❌'} ${asset.symbol} - ${asset.icon}`);
88
+ }
89
+ console.log('');
90
+ }
91
+
92
+ // Check if .com URLs could work as .info
93
+ if (sources.keepkeyCom.length > 0) {
94
+ console.log('=== Testing if .com URLs work as .info ===');
95
+ const sample = sources.keepkeyCom.slice(0, 3);
96
+ for (const assetId of sample) {
97
+ const asset = assetData[assetId as keyof typeof assetData] as Asset;
98
+ if (asset.icon) {
99
+ const comUrl = asset.icon;
100
+ const infoUrl = asset.icon.replace('api.keepkey.com', 'api.keepkey.info');
101
+
102
+ console.log(`\n${asset.symbol} (${asset.name})`);
103
+ console.log(` .com URL: ${comUrl}`);
104
+ const comWorks = await checkIcon(comUrl);
105
+ console.log(` .com test: ${comWorks ? '✅' : '❌'}`);
106
+
107
+ console.log(` .info URL: ${infoUrl}`);
108
+ const infoWorks = await checkIcon(infoUrl);
109
+ console.log(` .info test: ${infoWorks ? '✅' : '❌'}`);
110
+ }
111
+ }
112
+ }
113
+
114
+ // Export results
115
+ const results = {
116
+ summary: {
117
+ total: entries.length,
118
+ ...Object.fromEntries(
119
+ Object.entries(sources).map(([key, val]) => [key, val.length])
120
+ ),
121
+ },
122
+ keepkeyComAssets: sources.keepkeyCom,
123
+ keepkeyInfoAssets: sources.keepkeyInfo,
124
+ };
125
+
126
+ await Bun.write('icon-sources-analysis.json', JSON.stringify(results, null, 2));
127
+ console.log('\n\nResults written to: icon-sources-analysis.json');
128
+ }
129
+
130
+ main().catch(console.error);
@@ -0,0 +1,95 @@
1
+ #!/usr/bin/env bun
2
+ /*
3
+ * Apply Icon Migration to Asset Data
4
+ * Updates generatedAssetData.json with new KeepKey CDN URLs
5
+ */
6
+
7
+ import assetData from '../src/generatedAssetData.json';
8
+ import migrationData from './icon-updates.json';
9
+ import { writeFileSync } from 'fs';
10
+ import { join } from 'path';
11
+
12
+ interface Asset {
13
+ symbol: string;
14
+ name: string;
15
+ chainId: string;
16
+ icon?: string;
17
+ assetId: string;
18
+ decimals: number;
19
+ isNative?: boolean;
20
+ }
21
+
22
+ async function verifyIcon(url: string): Promise<boolean> {
23
+ try {
24
+ const response = await fetch(url, { method: 'HEAD' });
25
+ return response.ok;
26
+ } catch {
27
+ return false;
28
+ }
29
+ }
30
+
31
+ async function main() {
32
+ console.log('=== Applying Icon Migration ===\n');
33
+
34
+ const updates = migrationData.updates;
35
+ const assetDataCopy = JSON.parse(JSON.stringify(assetData)) as Record<string, Asset>;
36
+
37
+ let updatedCount = 0;
38
+ let verifiedCount = 0;
39
+ const failedVerifications: string[] = [];
40
+
41
+ console.log('Verifying new icon URLs before applying...\n');
42
+
43
+ for (const [assetId, newUrl] of Object.entries(updates)) {
44
+ const asset = assetDataCopy[assetId];
45
+ if (!asset) {
46
+ console.log(`⚠️ Asset not found: ${assetId}`);
47
+ continue;
48
+ }
49
+
50
+ console.log(`Checking ${asset.symbol} (${asset.name})...`);
51
+ const isAccessible = await verifyIcon(newUrl as string);
52
+
53
+ if (isAccessible) {
54
+ console.log(` ✅ Icon accessible: ${newUrl}`);
55
+ asset.icon = newUrl as string;
56
+ updatedCount++;
57
+ verifiedCount++;
58
+ } else {
59
+ console.log(` ❌ Icon NOT accessible: ${newUrl}`);
60
+ failedVerifications.push(`${asset.symbol} - ${assetId}`);
61
+ }
62
+ }
63
+
64
+ console.log(`\n=== Verification Summary ===`);
65
+ console.log(`Total to update: ${Object.keys(updates).length}`);
66
+ console.log(`Verified and accessible: ${verifiedCount}`);
67
+ console.log(`Failed verification: ${failedVerifications.length}`);
68
+
69
+ if (failedVerifications.length > 0) {
70
+ console.log(`\n❌ Failed assets:`);
71
+ failedVerifications.forEach(asset => console.log(` - ${asset}`));
72
+ console.log(`\nERROR: Not all icons are accessible. Please upload icons first.`);
73
+ console.log(`Run: ./scripts/upload-icons.sh`);
74
+ process.exit(1);
75
+ }
76
+
77
+ // Backup existing data
78
+ const backupPath = join(import.meta.dir, '../src/generatedAssetData.json.backup-before-migration');
79
+ writeFileSync(backupPath, JSON.stringify(assetData, null, 2));
80
+ console.log(`\n✅ Backup created: ${backupPath}`);
81
+
82
+ // Write updated data
83
+ const outputPath = join(import.meta.dir, '../src/generatedAssetData.json');
84
+ writeFileSync(outputPath, JSON.stringify(assetDataCopy, null, 2));
85
+ console.log(`✅ Updated asset data: ${outputPath}`);
86
+
87
+ console.log(`\n=== Migration Complete ===`);
88
+ console.log(`${updatedCount} assets updated with new icon URLs`);
89
+ console.log('\nNext steps:');
90
+ console.log('1. Verify icons: bun run scripts/check-critical-icons.ts');
91
+ console.log('2. Rebuild package: bun run build');
92
+ console.log('3. Test in application');
93
+ }
94
+
95
+ main().catch(console.error);
@@ -0,0 +1,142 @@
1
+ #!/usr/bin/env bun
2
+ /*
3
+ * Critical Icon Checker Script
4
+ * Checks only EIP155 native gas assets and a sample of other assets
5
+ */
6
+
7
+ import assetData from '../src/generatedAssetData.json';
8
+
9
+ interface Asset {
10
+ symbol: string;
11
+ name: string;
12
+ chainId: string;
13
+ icon?: string;
14
+ assetId: string;
15
+ decimals: number;
16
+ isNative?: boolean;
17
+ }
18
+
19
+ interface IconStatus {
20
+ assetId: string;
21
+ name: string;
22
+ symbol: string;
23
+ isNative: boolean;
24
+ icon: string | undefined;
25
+ status: 'ok' | 'missing' | 'error' | 'invalid';
26
+ httpCode?: number;
27
+ }
28
+
29
+ async function checkIcon(url: string | undefined): Promise<{ status: 'ok' | 'missing' | 'error' | 'invalid'; httpCode?: number }> {
30
+ if (!url) {
31
+ return { status: 'missing' };
32
+ }
33
+
34
+ try {
35
+ const response = await fetch(url, { method: 'HEAD' });
36
+ if (response.ok) {
37
+ return { status: 'ok', httpCode: response.status };
38
+ } else {
39
+ return { status: 'error', httpCode: response.status };
40
+ }
41
+ } catch (error) {
42
+ return { status: 'invalid' };
43
+ }
44
+ }
45
+
46
+ async function main() {
47
+ const entries = Object.entries(assetData as Record<string, Asset>);
48
+
49
+ // Filter to just native assets and EIP155 chains
50
+ const nativeAssets = entries.filter(([_, asset]) => asset.isNative);
51
+ const eip155Native = nativeAssets.filter(([assetId]) => assetId.startsWith('eip155:'));
52
+
53
+ console.log(`Total assets: ${entries.length}`);
54
+ console.log(`Native assets: ${nativeAssets.length}`);
55
+ console.log(`EIP155 native assets: ${eip155Native.length}`);
56
+ console.log('');
57
+
58
+ console.log('Checking EIP155 native gas assets...');
59
+ const results: IconStatus[] = [];
60
+
61
+ for (const [assetId, asset] of eip155Native) {
62
+ const result = await checkIcon(asset.icon);
63
+ results.push({
64
+ assetId,
65
+ name: asset.name,
66
+ symbol: asset.symbol,
67
+ isNative: asset.isNative || false,
68
+ icon: asset.icon,
69
+ status: result.status,
70
+ httpCode: result.httpCode,
71
+ });
72
+
73
+ // Show progress
74
+ const statusEmoji = result.status === 'ok' ? '✅' : '❌';
75
+ console.log(`${statusEmoji} ${asset.symbol.padEnd(8)} ${asset.name.padEnd(30)} ${asset.chainId}`);
76
+ if (result.status !== 'ok') {
77
+ console.log(` Icon: ${asset.icon || 'MISSING'}`);
78
+ console.log(` Status: ${result.status}${result.httpCode ? ` (${result.httpCode})` : ''}`);
79
+ }
80
+ }
81
+
82
+ console.log('');
83
+ console.log('Checking other native assets...');
84
+
85
+ const otherNative = nativeAssets.filter(([assetId]) => !assetId.startsWith('eip155:'));
86
+ for (const [assetId, asset] of otherNative) {
87
+ const result = await checkIcon(asset.icon);
88
+ results.push({
89
+ assetId,
90
+ name: asset.name,
91
+ symbol: asset.symbol,
92
+ isNative: asset.isNative || false,
93
+ icon: asset.icon,
94
+ status: result.status,
95
+ httpCode: result.httpCode,
96
+ });
97
+
98
+ const statusEmoji = result.status === 'ok' ? '✅' : '❌';
99
+ console.log(`${statusEmoji} ${asset.symbol.padEnd(8)} ${asset.name.padEnd(30)} ${asset.chainId}`);
100
+ if (result.status !== 'ok') {
101
+ console.log(` Icon: ${asset.icon || 'MISSING'}`);
102
+ console.log(` Status: ${result.status}${result.httpCode ? ` (${result.httpCode})` : ''}`);
103
+ }
104
+ }
105
+
106
+ console.log('');
107
+ console.log('=== Summary ===');
108
+ const broken = results.filter(r => r.status !== 'ok');
109
+ const eip155Broken = broken.filter(r => r.assetId.startsWith('eip155:'));
110
+
111
+ console.log(`Total native checked: ${results.length}`);
112
+ console.log(`EIP155 native checked: ${eip155Native.length}`);
113
+ console.log(`Broken icons: ${broken.length}`);
114
+ console.log(`EIP155 broken: ${eip155Broken.length}`);
115
+
116
+ if (broken.length > 0) {
117
+ console.log('');
118
+ console.log('=== Assets Needing Icon Fixes ===');
119
+ for (const asset of broken) {
120
+ console.log(`${asset.symbol} (${asset.name})`);
121
+ console.log(` Asset ID: ${asset.assetId}`);
122
+ console.log(` Current Icon: ${asset.icon || 'NONE'}`);
123
+ console.log('');
124
+ }
125
+ }
126
+
127
+ // Export results
128
+ await Bun.write('critical-icon-results.json', JSON.stringify({
129
+ summary: {
130
+ totalNative: results.length,
131
+ eip155Native: eip155Native.length,
132
+ broken: broken.length,
133
+ eip155Broken: eip155Broken.length,
134
+ },
135
+ brokenAssets: broken,
136
+ allResults: results,
137
+ }, null, 2));
138
+
139
+ console.log('Results written to: critical-icon-results.json');
140
+ }
141
+
142
+ main().catch(console.error);
@@ -0,0 +1,147 @@
1
+ #!/usr/bin/env bun
2
+ /*
3
+ * Icon Checker Script
4
+ * Checks all icons in generatedAssetData.json for validity
5
+ */
6
+
7
+ import assetData from '../src/generatedAssetData.json';
8
+
9
+ interface Asset {
10
+ symbol: string;
11
+ name: string;
12
+ chainId: string;
13
+ icon?: string;
14
+ assetId: string;
15
+ decimals: number;
16
+ isNative?: boolean;
17
+ }
18
+
19
+ interface IconStatus {
20
+ assetId: string;
21
+ name: string;
22
+ symbol: string;
23
+ isNative: boolean;
24
+ icon: string | undefined;
25
+ status: 'ok' | 'missing' | 'error' | 'invalid';
26
+ httpCode?: number;
27
+ }
28
+
29
+ async function checkIcon(url: string | undefined): Promise<{ status: 'ok' | 'missing' | 'error' | 'invalid'; httpCode?: number }> {
30
+ if (!url) {
31
+ return { status: 'missing' };
32
+ }
33
+
34
+ try {
35
+ const response = await fetch(url, { method: 'HEAD' });
36
+ if (response.ok) {
37
+ return { status: 'ok', httpCode: response.status };
38
+ } else {
39
+ return { status: 'error', httpCode: response.status };
40
+ }
41
+ } catch (error) {
42
+ return { status: 'invalid' };
43
+ }
44
+ }
45
+
46
+ async function main() {
47
+ const results: IconStatus[] = [];
48
+ const entries = Object.entries(assetData as Record<string, Asset>);
49
+
50
+ console.log(`Checking ${entries.length} assets...`);
51
+ console.log('');
52
+
53
+ // Check all assets
54
+ for (const [assetId, asset] of entries) {
55
+ const result = await checkIcon(asset.icon);
56
+ results.push({
57
+ assetId,
58
+ name: asset.name,
59
+ symbol: asset.symbol,
60
+ isNative: asset.isNative || false,
61
+ icon: asset.icon,
62
+ status: result.status,
63
+ httpCode: result.httpCode,
64
+ });
65
+ }
66
+
67
+ // Filter and display results
68
+ const eip155Native = results.filter(r => r.isNative && r.assetId.startsWith('eip155:'));
69
+ const allNative = results.filter(r => r.isNative);
70
+ const broken = results.filter(r => r.status !== 'ok');
71
+ const eip155Broken = broken.filter(r => r.assetId.startsWith('eip155:'));
72
+
73
+ console.log('=== Summary ===');
74
+ console.log(`Total assets: ${results.length}`);
75
+ console.log(`Total native assets: ${allNative.length}`);
76
+ console.log(`EIP155 native assets: ${eip155Native.length}`);
77
+ console.log(`Total broken icons: ${broken.length}`);
78
+ console.log(`EIP155 broken icons: ${eip155Broken.length}`);
79
+ console.log('');
80
+
81
+ // Show EIP155 native gas assets
82
+ console.log('=== EIP155 Native Gas Assets ===');
83
+ for (const asset of eip155Native) {
84
+ console.log(`${asset.status === 'ok' ? '✅' : '❌'} ${asset.symbol.padEnd(8)} ${asset.name.padEnd(30)} ${asset.assetId}`);
85
+ if (asset.status !== 'ok') {
86
+ console.log(` Icon: ${asset.icon || 'MISSING'}`);
87
+ console.log(` Status: ${asset.status}${asset.httpCode ? ` (${asset.httpCode})` : ''}`);
88
+ }
89
+ }
90
+ console.log('');
91
+
92
+ // Show all broken native assets
93
+ const brokenNative = allNative.filter(r => r.status !== 'ok');
94
+ if (brokenNative.length > 0) {
95
+ console.log('=== Broken Native Asset Icons ===');
96
+ for (const asset of brokenNative) {
97
+ console.log(`❌ ${asset.symbol.padEnd(8)} ${asset.name.padEnd(30)} ${asset.assetId}`);
98
+ console.log(` Icon: ${asset.icon || 'MISSING'}`);
99
+ console.log(` Status: ${asset.status}${asset.httpCode ? ` (${asset.httpCode})` : ''}`);
100
+ }
101
+ console.log('');
102
+ }
103
+
104
+ // Show broken icons by source
105
+ const keepkeyBroken = broken.filter(r => r.icon?.includes('api.keepkey.com'));
106
+ const coingeckoBroken = broken.filter(r => r.icon?.includes('coingecko.com'));
107
+ const missingIcons = broken.filter(r => !r.icon);
108
+
109
+ console.log('=== Broken Icons By Source ===');
110
+ console.log(`KeepKey API: ${keepkeyBroken.length}`);
111
+ console.log(`CoinGecko: ${coingeckoBroken.length}`);
112
+ console.log(`Missing: ${missingIcons.length}`);
113
+ console.log('');
114
+
115
+ // Export detailed results
116
+ const detailedOutput = {
117
+ summary: {
118
+ total: results.length,
119
+ totalNative: allNative.length,
120
+ eip155Native: eip155Native.length,
121
+ broken: broken.length,
122
+ eip155Broken: eip155Broken.length,
123
+ },
124
+ brokenAssets: broken.map(r => ({
125
+ assetId: r.assetId,
126
+ name: r.name,
127
+ symbol: r.symbol,
128
+ isNative: r.isNative,
129
+ icon: r.icon,
130
+ status: r.status,
131
+ httpCode: r.httpCode,
132
+ })),
133
+ eip155NativeAssets: eip155Native.map(r => ({
134
+ assetId: r.assetId,
135
+ name: r.name,
136
+ symbol: r.symbol,
137
+ icon: r.icon,
138
+ status: r.status,
139
+ httpCode: r.httpCode,
140
+ })),
141
+ };
142
+
143
+ await Bun.write('icon-check-results.json', JSON.stringify(detailedOutput, null, 2));
144
+ console.log('Detailed results written to: icon-check-results.json');
145
+ }
146
+
147
+ main().catch(console.error);
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env bun
2
+ /*
3
+ * Fix Icon URLs Script
4
+ * Updates generatedAssetData.json with working icon URLs from DigitalOcean
5
+ */
6
+
7
+ import * as fs from 'fs';
8
+ import * as path from 'path';
9
+
10
+ const assetDataPath = path.join(import.meta.dir, '..', 'src', 'generatedAssetData.json');
11
+ const assetData = JSON.parse(fs.readFileSync(assetDataPath, 'utf-8'));
12
+
13
+ // Assets to fix with their new icon URLs
14
+ const fixes = [
15
+ {
16
+ assetId: 'cosmos:cosmoshub-4/slip44:118',
17
+ oldIcon: 'https://assets.coingecko.com/coins/images/16724/thumb/atom.png',
18
+ newIcon: 'https://keepkey.sfo3.cdn.digitaloceanspaces.com/coins/Y29zbW9zOmNvc21vc2h1Yi00L3NsaXA0NDoxMTg=.png',
19
+ name: 'Cosmos (ATOM)',
20
+ },
21
+ {
22
+ assetId: 'cosmos:mayachain-mainnet-v1/slip44:931',
23
+ oldIcon: 'https://assets.coingecko.com/coins/images/25662/small/cacao.png',
24
+ newIcon: 'https://keepkey.sfo3.cdn.digitaloceanspaces.com/coins/Y29zbW9zOm1heWFjaGFpbi1tYWlubmV0LXYxL3NsaXA0NDo5MzE=.png',
25
+ name: 'Mayachain (CACAO)',
26
+ },
27
+ {
28
+ assetId: 'bip122:12a765e31ffd4059bada1e25190f6e98/slip44:2',
29
+ oldIcon: 'https://assets.coingecko.com/coins/images/16724/thumb/ltc.png',
30
+ newIcon: 'https://keepkey.sfo3.cdn.digitaloceanspaces.com/coins/YmlwMTIyOjEyYTc2NWUzMWZmZDQwNTliYWRhMWUyNTE5MGY2ZTk4L3NsaXA0NDoy.png',
31
+ name: 'Litecoin (LTC)',
32
+ },
33
+ ];
34
+
35
+ console.log('Fixing icon URLs in generatedAssetData.json...\n');
36
+
37
+ let changesMade = 0;
38
+
39
+ for (const fix of fixes) {
40
+ if (assetData[fix.assetId]) {
41
+ console.log(`Updating ${fix.name}`);
42
+ console.log(` Asset ID: ${fix.assetId}`);
43
+ console.log(` Old Icon: ${fix.oldIcon}`);
44
+ console.log(` New Icon: ${fix.newIcon}`);
45
+
46
+ assetData[fix.assetId].icon = fix.newIcon;
47
+ changesMade++;
48
+ console.log(' ✅ Updated\n');
49
+ } else {
50
+ console.log(`⚠️ Asset not found: ${fix.assetId}\n`);
51
+ }
52
+ }
53
+
54
+ if (changesMade > 0) {
55
+ // Write back to file
56
+ fs.writeFileSync(assetDataPath, JSON.stringify(assetData, null, 2));
57
+ console.log(`\n✅ Successfully updated ${changesMade} icon URLs`);
58
+ console.log(`📝 File updated: ${assetDataPath}`);
59
+ } else {
60
+ console.log('\n⚠️ No changes made');
61
+ }
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env bun
2
+ /*
3
+ * Fix KeepKey.com URLs
4
+ * Replace api.keepkey.com with api.keepkey.info
5
+ */
6
+
7
+ import * as fs from 'fs';
8
+ import * as path from 'path';
9
+
10
+ const assetDataPath = path.join(import.meta.dir, '..', 'src', 'generatedAssetData.json');
11
+ const assetData = JSON.parse(fs.readFileSync(assetDataPath, 'utf-8'));
12
+
13
+ interface Asset {
14
+ symbol: string;
15
+ name: string;
16
+ icon?: string;
17
+ [key: string]: any;
18
+ }
19
+
20
+ console.log('Fixing api.keepkey.com URLs...\n');
21
+
22
+ let changesMade = 0;
23
+ const changes: Array<{ assetId: string; symbol: string; name: string; oldUrl: string; newUrl: string }> = [];
24
+
25
+ for (const [assetId, asset] of Object.entries(assetData) as Array<[string, Asset]>) {
26
+ if (asset.icon && asset.icon.includes('api.keepkey.com')) {
27
+ const oldUrl = asset.icon;
28
+ const newUrl = oldUrl.replace('api.keepkey.com', 'api.keepkey.info');
29
+
30
+ asset.icon = newUrl;
31
+ changesMade++;
32
+
33
+ changes.push({
34
+ assetId,
35
+ symbol: asset.symbol,
36
+ name: asset.name,
37
+ oldUrl,
38
+ newUrl,
39
+ });
40
+
41
+ if (changesMade <= 10) {
42
+ console.log(`${changesMade}. ${asset.symbol} (${asset.name})`);
43
+ console.log(` Old: ${oldUrl}`);
44
+ console.log(` New: ${newUrl}`);
45
+ console.log('');
46
+ }
47
+ }
48
+ }
49
+
50
+ if (changesMade > 10) {
51
+ console.log(`... and ${changesMade - 10} more assets\n`);
52
+ }
53
+
54
+ if (changesMade > 0) {
55
+ // Write back to file
56
+ fs.writeFileSync(assetDataPath, JSON.stringify(assetData, null, 2));
57
+
58
+ console.log('=== Summary ===');
59
+ console.log(`✅ Successfully updated ${changesMade} icon URLs`);
60
+ console.log(`📝 File updated: ${assetDataPath}`);
61
+ console.log('');
62
+
63
+ // Save detailed changes
64
+ await Bun.write('keepkey-com-fixes.json', JSON.stringify(changes, null, 2));
65
+ console.log('📋 Detailed changes written to: keepkey-com-fixes.json');
66
+ } else {
67
+ console.log('\n⚠️ No keepkey.com URLs found to fix');
68
+ }