@pioneer-platform/pioneer-discovery 8.15.32 ā 8.15.33
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/CHANGELOG.md +8 -0
- package/lib/generatedAssetData.json +14224 -7112
- package/package.json +2 -2
- package/scripts/add-decimals-from-shapeshift.js +108 -0
- package/scripts/download-with-coingecko-api.js +1 -1
- package/scripts/fix-icon-permissions.js +170 -0
- package/scripts/upload-all-case-variants.sh +73 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pioneer-platform/pioneer-discovery",
|
|
3
|
-
"version": "8.15.
|
|
3
|
+
"version": "8.15.33",
|
|
4
4
|
"main": "./lib/index.js",
|
|
5
5
|
"types": "./lib/main.d.ts",
|
|
6
6
|
"_moduleAliases": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
},
|
|
29
29
|
"gitHead": "a76012f6693a12181c4744e53e977a9eaeef0ed3",
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@pioneer-platform/pioneer-caip": "^9.10.
|
|
31
|
+
"@pioneer-platform/pioneer-caip": "^9.10.10",
|
|
32
32
|
"ethers": "5.7.2"
|
|
33
33
|
}
|
|
34
34
|
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Add decimals/precision from ShapeShift data to Pioneer assets
|
|
4
|
+
*
|
|
5
|
+
* ShapeShift structure:
|
|
6
|
+
* - encodedAssets: array of [assetIdx, name, precision, color, icon[], symbol, relatedAssetKey, isPool]
|
|
7
|
+
* FIELDS order: ['assetIdx', 'name', 'precision', 'color', 'icon', 'symbol', 'relatedAssetKey', 'isPool']
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
|
|
13
|
+
const TAG = ' | add-decimals-from-shapeshift | ';
|
|
14
|
+
|
|
15
|
+
// Paths
|
|
16
|
+
const SHAPESHIFT_DATA_PATH = '/Users/highlander/WebstormProjects/web/src/lib/asset-service/service/encodedAssetData.json';
|
|
17
|
+
const PIONEER_ASSETS_PATH = path.join(__dirname, '../src/generatedAssetData.json');
|
|
18
|
+
const BACKUP_PATH = path.join(__dirname, '../src/generatedAssetData.json.backup-decimals');
|
|
19
|
+
|
|
20
|
+
console.log(TAG, 'Loading ShapeShift asset data...');
|
|
21
|
+
const shapeshiftData = JSON.parse(fs.readFileSync(SHAPESHIFT_DATA_PATH, 'utf8'));
|
|
22
|
+
const { assetIdPrefixes, encodedAssetIds, encodedAssets } = shapeshiftData;
|
|
23
|
+
|
|
24
|
+
console.log(TAG, `Loaded ${encodedAssetIds.length} ShapeShift assets`);
|
|
25
|
+
|
|
26
|
+
// Decode ShapeShift asset IDs
|
|
27
|
+
function decodeAssetId(encodedId, prefixes) {
|
|
28
|
+
const colonIndex = encodedId.lastIndexOf(':');
|
|
29
|
+
const prefixIdx = Number(encodedId.substring(0, colonIndex));
|
|
30
|
+
const assetReference = encodedId.substring(colonIndex + 1);
|
|
31
|
+
return prefixes[prefixIdx] + ':' + assetReference;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Field index for precision
|
|
35
|
+
const FIELD_PRECISION = 2;
|
|
36
|
+
|
|
37
|
+
// Build ShapeShift precision map: CAIP ID -> decimals
|
|
38
|
+
const shapeshiftDecimalsMap = new Map();
|
|
39
|
+
|
|
40
|
+
encodedAssetIds.forEach((encodedId, idx) => {
|
|
41
|
+
const assetId = decodeAssetId(encodedId, assetIdPrefixes);
|
|
42
|
+
const encodedAsset = encodedAssets[idx];
|
|
43
|
+
const precision = encodedAsset[FIELD_PRECISION];
|
|
44
|
+
|
|
45
|
+
if (precision !== undefined && precision !== null) {
|
|
46
|
+
shapeshiftDecimalsMap.set(assetId.toLowerCase(), precision);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
console.log(TAG, `ShapeShift assets with precision: ${shapeshiftDecimalsMap.size}`);
|
|
51
|
+
|
|
52
|
+
// Load Pioneer assets
|
|
53
|
+
console.log(TAG, 'Loading Pioneer assets...');
|
|
54
|
+
const pioneerAssets = JSON.parse(fs.readFileSync(PIONEER_ASSETS_PATH, 'utf8'));
|
|
55
|
+
const totalPioneerAssets = Object.keys(pioneerAssets).length;
|
|
56
|
+
console.log(TAG, `Loaded ${totalPioneerAssets} Pioneer assets`);
|
|
57
|
+
|
|
58
|
+
// Backup the original file
|
|
59
|
+
console.log(TAG, 'Creating backup...');
|
|
60
|
+
fs.writeFileSync(BACKUP_PATH, JSON.stringify(pioneerAssets, null, 2));
|
|
61
|
+
console.log(TAG, `Backup saved to: ${BACKUP_PATH}`);
|
|
62
|
+
|
|
63
|
+
// Add decimals to Pioneer assets
|
|
64
|
+
let added = 0;
|
|
65
|
+
let alreadyHad = 0;
|
|
66
|
+
let notFound = 0;
|
|
67
|
+
|
|
68
|
+
Object.entries(pioneerAssets).forEach(([caipId, asset]) => {
|
|
69
|
+
const shapeshiftPrecision = shapeshiftDecimalsMap.get(caipId.toLowerCase());
|
|
70
|
+
|
|
71
|
+
if (asset.decimals !== undefined) {
|
|
72
|
+
alreadyHad++;
|
|
73
|
+
} else if (shapeshiftPrecision !== undefined) {
|
|
74
|
+
asset.decimals = shapeshiftPrecision;
|
|
75
|
+
added++;
|
|
76
|
+
} else {
|
|
77
|
+
notFound++;
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
console.log(TAG, '\n========================================');
|
|
82
|
+
console.log(TAG, 'RESULTS');
|
|
83
|
+
console.log(TAG, '========================================');
|
|
84
|
+
console.log(TAG, `Total Pioneer assets: ${totalPioneerAssets}`);
|
|
85
|
+
console.log(TAG, `Already had decimals: ${alreadyHad}`);
|
|
86
|
+
console.log(TAG, `Added from ShapeShift: ${added} š`);
|
|
87
|
+
console.log(TAG, `Not found in ShapeShift: ${notFound}`);
|
|
88
|
+
console.log(TAG, `Coverage: ${(((alreadyHad + added) / totalPioneerAssets) * 100).toFixed(1)}%`);
|
|
89
|
+
|
|
90
|
+
// Save updated Pioneer assets
|
|
91
|
+
console.log(TAG, '\nSaving updated assets...');
|
|
92
|
+
fs.writeFileSync(PIONEER_ASSETS_PATH, JSON.stringify(pioneerAssets, null, 2));
|
|
93
|
+
console.log(TAG, `ā
Updated assets saved to: ${PIONEER_ASSETS_PATH}`);
|
|
94
|
+
|
|
95
|
+
// Show sample of assets that got decimals added
|
|
96
|
+
console.log(TAG, '\n========================================');
|
|
97
|
+
console.log(TAG, 'SAMPLE ASSETS WITH DECIMALS ADDED (first 10)');
|
|
98
|
+
console.log(TAG, '========================================');
|
|
99
|
+
|
|
100
|
+
let sampleCount = 0;
|
|
101
|
+
Object.entries(pioneerAssets).forEach(([caipId, asset]) => {
|
|
102
|
+
if (sampleCount < 10 && asset.decimals !== undefined && shapeshiftDecimalsMap.has(caipId.toLowerCase())) {
|
|
103
|
+
console.log(`${(asset.symbol || 'UNKNOWN').padEnd(10)} decimals: ${asset.decimals} ${caipId.slice(0, 60)}`);
|
|
104
|
+
sampleCount++;
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
console.log(TAG, '\nā
Done!');
|
|
@@ -226,7 +226,7 @@ async function processAsset(assetId, assetData, stats, progress, failed) {
|
|
|
226
226
|
if (fileSize > 0) {
|
|
227
227
|
stats.alreadyLocal++;
|
|
228
228
|
progress.processed[assetId] = 'local';
|
|
229
|
-
assetData.icon = `https://api.keepkey.
|
|
229
|
+
assetData.icon = `https://api.keepkey.info/coins/${encoded}.png`;
|
|
230
230
|
return true;
|
|
231
231
|
}
|
|
232
232
|
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* Fix Icon Permissions on S3
|
|
5
|
+
*
|
|
6
|
+
* This script:
|
|
7
|
+
* 1. Lists all icons in the S3 bucket
|
|
8
|
+
* 2. Sets public-read ACL on each icon
|
|
9
|
+
* 3. Verifies accessibility
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const { execSync } = require('child_process');
|
|
13
|
+
const https = require('https');
|
|
14
|
+
|
|
15
|
+
// Configuration
|
|
16
|
+
const S3_ENDPOINT = 'https://sfo3.digitaloceanspaces.com';
|
|
17
|
+
const S3_BUCKET = 'keepkey';
|
|
18
|
+
const S3_REGION = 'sfo3';
|
|
19
|
+
const CDN_URL = 'https://keepkey.sfo3.cdn.digitaloceanspaces.com';
|
|
20
|
+
|
|
21
|
+
// AWS credentials
|
|
22
|
+
const AWS_ACCESS_KEY_ID = process.env.AWS_ACCESS_KEY_ID;
|
|
23
|
+
const AWS_SECRET_ACCESS_KEY = process.env.AWS_SECRET_ACCESS_KEY;
|
|
24
|
+
|
|
25
|
+
if (!AWS_ACCESS_KEY_ID || !AWS_SECRET_ACCESS_KEY) {
|
|
26
|
+
console.error('ā Missing AWS credentials');
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Check if URL is accessible
|
|
32
|
+
*/
|
|
33
|
+
async function urlExists(url, timeout = 5000) {
|
|
34
|
+
return new Promise((resolve) => {
|
|
35
|
+
const req = https.request(url, { method: 'HEAD', timeout }, (res) => {
|
|
36
|
+
resolve(res.statusCode === 200);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
req.on('error', () => resolve(false));
|
|
40
|
+
req.on('timeout', () => {
|
|
41
|
+
req.destroy();
|
|
42
|
+
resolve(false);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
req.end();
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Set ACL to public-read
|
|
51
|
+
*/
|
|
52
|
+
function setPublicAcl(s3Key) {
|
|
53
|
+
try {
|
|
54
|
+
const cmd = `AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} aws s3api put-object-acl --bucket ${S3_BUCKET} --key "${s3Key}" --acl public-read --endpoint-url=${S3_ENDPOINT}`;
|
|
55
|
+
|
|
56
|
+
execSync(cmd, { stdio: 'pipe' });
|
|
57
|
+
return true;
|
|
58
|
+
} catch (error) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* List all objects in S3 bucket with coins/ prefix
|
|
65
|
+
*/
|
|
66
|
+
function listS3Objects() {
|
|
67
|
+
try {
|
|
68
|
+
const cmd = `AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} aws s3api list-objects-v2 --bucket ${S3_BUCKET} --prefix "coins/" --endpoint-url=${S3_ENDPOINT} --query "Contents[].Key" --output json`;
|
|
69
|
+
|
|
70
|
+
const output = execSync(cmd, { encoding: 'utf8' });
|
|
71
|
+
return JSON.parse(output);
|
|
72
|
+
} catch (error) {
|
|
73
|
+
console.error('ā Failed to list S3 objects:', error.message);
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Wait for specified milliseconds
|
|
80
|
+
*/
|
|
81
|
+
function sleep(ms) {
|
|
82
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Main execution
|
|
87
|
+
*/
|
|
88
|
+
async function main() {
|
|
89
|
+
console.log('š Starting ACL fix process...\n');
|
|
90
|
+
console.log(`āļø S3 bucket: ${S3_BUCKET}`);
|
|
91
|
+
console.log(`š CDN URL: ${CDN_URL}\n`);
|
|
92
|
+
|
|
93
|
+
// List all objects
|
|
94
|
+
console.log('š Listing all icons in S3...');
|
|
95
|
+
const objects = listS3Objects();
|
|
96
|
+
|
|
97
|
+
if (objects.length === 0) {
|
|
98
|
+
console.log('ā No objects found or failed to list');
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
console.log(`š Found ${objects.length} icons\n`);
|
|
103
|
+
|
|
104
|
+
const stats = {
|
|
105
|
+
total: 0,
|
|
106
|
+
alreadyPublic: 0,
|
|
107
|
+
fixed: 0,
|
|
108
|
+
failed: 0,
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// Process each object
|
|
112
|
+
for (const s3Key of objects) {
|
|
113
|
+
stats.total++;
|
|
114
|
+
const cdnUrl = `${CDN_URL}/${s3Key}`;
|
|
115
|
+
const fileName = s3Key.split('/').pop();
|
|
116
|
+
|
|
117
|
+
console.log(`\nš [${stats.total}/${objects.length}] ${fileName}`);
|
|
118
|
+
|
|
119
|
+
// Check current accessibility
|
|
120
|
+
const accessible = await urlExists(cdnUrl);
|
|
121
|
+
|
|
122
|
+
if (accessible) {
|
|
123
|
+
console.log(` ā
Already public`);
|
|
124
|
+
stats.alreadyPublic++;
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
console.log(` ā ļø Not accessible - fixing ACL...`);
|
|
129
|
+
const fixed = setPublicAcl(s3Key);
|
|
130
|
+
|
|
131
|
+
if (!fixed) {
|
|
132
|
+
console.log(` ā Failed to set ACL`);
|
|
133
|
+
stats.failed++;
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Wait for propagation
|
|
138
|
+
await sleep(500);
|
|
139
|
+
|
|
140
|
+
// Verify
|
|
141
|
+
const nowAccessible = await urlExists(cdnUrl);
|
|
142
|
+
if (nowAccessible) {
|
|
143
|
+
console.log(` ā
Fixed!`);
|
|
144
|
+
stats.fixed++;
|
|
145
|
+
} else {
|
|
146
|
+
console.log(` ā Still not accessible`);
|
|
147
|
+
stats.failed++;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Small delay between operations
|
|
151
|
+
await sleep(100);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Print summary
|
|
155
|
+
console.log('\n' + '='.repeat(80));
|
|
156
|
+
console.log('š FINAL SUMMARY');
|
|
157
|
+
console.log('='.repeat(80));
|
|
158
|
+
console.log(`Total icons: ${stats.total}`);
|
|
159
|
+
console.log(`Already public: ${stats.alreadyPublic}`);
|
|
160
|
+
console.log(`Fixed: ${stats.fixed}`);
|
|
161
|
+
console.log(`Failed: ${stats.failed}`);
|
|
162
|
+
console.log('='.repeat(80));
|
|
163
|
+
|
|
164
|
+
console.log('\nā
ACL fix process complete!\n');
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
main().catch(err => {
|
|
168
|
+
console.error('ā Fatal error:', err);
|
|
169
|
+
process.exit(1);
|
|
170
|
+
});
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Upload all case variants for ERC20/BEP20 tokens
|
|
4
|
+
# For each token with an address, upload both lowercase and checksummed variants
|
|
5
|
+
|
|
6
|
+
export AWS_ACCESS_KEY_ID="DO00FXP8KK64LCXYAEZP"
|
|
7
|
+
export AWS_SECRET_ACCESS_KEY="Uyw/cq63rrQmFV9yy1HbovTSMNhLkEwImqPa88N/E/s"
|
|
8
|
+
|
|
9
|
+
COINS_DIR="/Users/highlander/WebstormProjects/keepkey-stack/projects/pioneer/services/pioneer-server/coins"
|
|
10
|
+
cd "$COINS_DIR"
|
|
11
|
+
|
|
12
|
+
echo "š Uploading all case variants for ERC20/BEP20 tokens"
|
|
13
|
+
echo "======================================================"
|
|
14
|
+
|
|
15
|
+
total=0
|
|
16
|
+
uploaded=0
|
|
17
|
+
|
|
18
|
+
# Process each PNG file
|
|
19
|
+
for file in *.png; do
|
|
20
|
+
# Decode the base64 filename to get the CAIP
|
|
21
|
+
caip=$(echo "$file" | sed 's/.png$//' | base64 -d 2>/dev/null)
|
|
22
|
+
|
|
23
|
+
# Check if it's an ERC20/BEP20 token (contains address)
|
|
24
|
+
if [[ "$caip" =~ (erc20|bep20):0x[a-fA-F0-9]{40} ]]; then
|
|
25
|
+
((total++))
|
|
26
|
+
|
|
27
|
+
# Extract the address
|
|
28
|
+
address=$(echo "$caip" | grep -o '0x[a-fA-F0-9]\{40\}')
|
|
29
|
+
|
|
30
|
+
# Create lowercase variant
|
|
31
|
+
lower_caip="${caip,,}" # Convert to lowercase
|
|
32
|
+
lower_encoded=$(echo -n "$lower_caip" | base64)
|
|
33
|
+
lower_file="${lower_encoded}.png"
|
|
34
|
+
|
|
35
|
+
# Create checksummed variant (simple approximation)
|
|
36
|
+
# Real checksumming would need proper keccak256, but we'll use uppercase
|
|
37
|
+
upper_caip=$(echo "$caip" | sed "s/$address/${address^^}/")
|
|
38
|
+
upper_encoded=$(echo -n "$upper_caip" | base64)
|
|
39
|
+
upper_file="${upper_encoded}.png"
|
|
40
|
+
|
|
41
|
+
echo ""
|
|
42
|
+
echo "š Processing: $caip"
|
|
43
|
+
|
|
44
|
+
# Upload lowercase variant if different from current
|
|
45
|
+
if [ "$file" != "$lower_file" ] && [ ! -f "$lower_file" ]; then
|
|
46
|
+
cp "$file" "$lower_file"
|
|
47
|
+
aws s3 cp "$lower_file" "s3://keepkey/coins/$lower_file" \
|
|
48
|
+
--endpoint-url=https://sfo3.digitaloceanspaces.com \
|
|
49
|
+
--acl public-read \
|
|
50
|
+
--region sfo3 \
|
|
51
|
+
--quiet
|
|
52
|
+
echo " ā
Uploaded lowercase variant"
|
|
53
|
+
((uploaded++))
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
# Upload checksummed variant if different from current
|
|
57
|
+
if [ "$file" != "$upper_file" ] && [ ! -f "$upper_file" ]; then
|
|
58
|
+
cp "$file" "$upper_file"
|
|
59
|
+
aws s3 cp "$upper_file" "s3://keepkey/coins/$upper_file" \
|
|
60
|
+
--endpoint-url=https://sfo3.digitaloceanspaces.com \
|
|
61
|
+
--acl public-read \
|
|
62
|
+
--region sfo3 \
|
|
63
|
+
--quiet
|
|
64
|
+
echo " ā
Uploaded checksummed variant"
|
|
65
|
+
((uploaded++))
|
|
66
|
+
fi
|
|
67
|
+
fi
|
|
68
|
+
done
|
|
69
|
+
|
|
70
|
+
echo ""
|
|
71
|
+
echo "======================================================"
|
|
72
|
+
echo "ā
Processed $total ERC20/BEP20 tokens"
|
|
73
|
+
echo "ā
Uploaded $uploaded additional case variants"
|