hd-wallet-ui 1.2.0 → 1.2.2
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 +5 -3
- package/src/address-derivation.js +50 -12
- package/src/app.js +2215 -440
- package/src/blockchain-trust.js +81 -28
- package/src/template.js +342 -206
- package/styles/main.css +1265 -43
package/src/blockchain-trust.js
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
* Revocation: [0x52][0x01][timestamp:4][txhash:32] = 38 bytes
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
import { apiUrl } from './address-derivation.js';
|
|
14
|
+
|
|
13
15
|
// =============================================================================
|
|
14
16
|
// Trust Levels (PGP-style)
|
|
15
17
|
// =============================================================================
|
|
@@ -41,6 +43,16 @@ const VERSION = 0x01;
|
|
|
41
43
|
// Legacy ASCII prefixes
|
|
42
44
|
const LEGACY_TRUST_PREFIX = 'TRUST';
|
|
43
45
|
const LEGACY_REVOKE_PREFIX = 'REVOKE';
|
|
46
|
+
const SOLANA_TRUST_RPC_ENDPOINTS = [
|
|
47
|
+
'https://solana-rpc.publicnode.com',
|
|
48
|
+
'https://mainnet.helius-rpc.com/?api-key=1d8740dc-e5f4-421c-b823-e1bad1889eda',
|
|
49
|
+
'https://api.mainnet-beta.solana.com',
|
|
50
|
+
];
|
|
51
|
+
const SOLANA_TRUST_MAX_SIGNATURES = 40;
|
|
52
|
+
const SOLANA_TRUST_REQUEST_DELAY_MS = 350;
|
|
53
|
+
const SOLANA_TRUST_UNAVAILABLE_COOLDOWN_MS = 5 * 60 * 1000;
|
|
54
|
+
let _solanaTrustLastRequestAt = 0;
|
|
55
|
+
let _solanaTrustUnavailableUntil = 0;
|
|
44
56
|
|
|
45
57
|
// =============================================================================
|
|
46
58
|
// Binary Encoding Helpers
|
|
@@ -420,39 +432,80 @@ export async function scanBitcoinTrustTransactions(address) {
|
|
|
420
432
|
* Uses RPC to get transactions with memo instructions.
|
|
421
433
|
*/
|
|
422
434
|
export async function scanSolanaTrustTransactions(address) {
|
|
435
|
+
const isRateLimited = (msg) => {
|
|
436
|
+
const t = (msg || '').toLowerCase();
|
|
437
|
+
return t.includes('429') || t.includes('rate') || t.includes('limit') || t.includes('too many');
|
|
438
|
+
};
|
|
439
|
+
const isEndpointUnavailable = (msg) => {
|
|
440
|
+
const t = (msg || '').toLowerCase();
|
|
441
|
+
return t.includes('403') || t.includes('404') || t.includes('forbidden') || t.includes('not found');
|
|
442
|
+
};
|
|
443
|
+
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
444
|
+
const waitForThrottle = async () => {
|
|
445
|
+
const elapsed = Date.now() - _solanaTrustLastRequestAt;
|
|
446
|
+
if (elapsed < SOLANA_TRUST_REQUEST_DELAY_MS) {
|
|
447
|
+
await sleep(SOLANA_TRUST_REQUEST_DELAY_MS - elapsed);
|
|
448
|
+
}
|
|
449
|
+
_solanaTrustLastRequestAt = Date.now();
|
|
450
|
+
};
|
|
451
|
+
const solanaRpcCall = async (method, params) => {
|
|
452
|
+
let lastError = 'Unknown Solana RPC error';
|
|
453
|
+
|
|
454
|
+
for (const endpoint of SOLANA_TRUST_RPC_ENDPOINTS) {
|
|
455
|
+
try {
|
|
456
|
+
await waitForThrottle();
|
|
457
|
+
const response = await fetch(apiUrl(endpoint), {
|
|
458
|
+
method: 'POST',
|
|
459
|
+
headers: { 'Content-Type': 'application/json' },
|
|
460
|
+
body: JSON.stringify({
|
|
461
|
+
jsonrpc: '2.0',
|
|
462
|
+
id: 1,
|
|
463
|
+
method,
|
|
464
|
+
params,
|
|
465
|
+
}),
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
if (!response.ok) {
|
|
469
|
+
lastError = `HTTP ${response.status}`;
|
|
470
|
+
continue;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
const data = await response.json();
|
|
474
|
+
if (data.error) {
|
|
475
|
+
lastError = data.error.message || 'Solana RPC returned error';
|
|
476
|
+
continue;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
return { ok: true, result: data.result };
|
|
480
|
+
} catch (e) {
|
|
481
|
+
lastError = e?.message || 'Solana RPC fetch failed';
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
return { ok: false, error: lastError };
|
|
486
|
+
};
|
|
487
|
+
|
|
423
488
|
try {
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
body: JSON.stringify({
|
|
428
|
-
jsonrpc: '2.0',
|
|
429
|
-
id: 1,
|
|
430
|
-
method: 'getSignaturesForAddress',
|
|
431
|
-
params: [address, { limit: 100 }],
|
|
432
|
-
}),
|
|
433
|
-
});
|
|
489
|
+
if (Date.now() < _solanaTrustUnavailableUntil) {
|
|
490
|
+
return [];
|
|
491
|
+
}
|
|
434
492
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
493
|
+
const sigResp = await solanaRpcCall('getSignaturesForAddress', [address, { limit: SOLANA_TRUST_MAX_SIGNATURES }]);
|
|
494
|
+
if (!sigResp.ok) {
|
|
495
|
+
if (isRateLimited(sigResp.error) || isEndpointUnavailable(sigResp.error)) {
|
|
496
|
+
_solanaTrustUnavailableUntil = Date.now() + SOLANA_TRUST_UNAVAILABLE_COOLDOWN_MS;
|
|
497
|
+
}
|
|
498
|
+
throw new Error(`Failed to fetch Solana signatures (${sigResp.error})`);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
const signatures = Array.isArray(sigResp.result) ? sigResp.result : [];
|
|
438
502
|
|
|
439
503
|
const trustTxs = [];
|
|
440
504
|
|
|
441
505
|
for (const sig of signatures) {
|
|
442
|
-
const
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
body: JSON.stringify({
|
|
446
|
-
jsonrpc: '2.0',
|
|
447
|
-
id: 1,
|
|
448
|
-
method: 'getTransaction',
|
|
449
|
-
params: [sig.signature, { encoding: 'jsonParsed' }],
|
|
450
|
-
}),
|
|
451
|
-
});
|
|
452
|
-
|
|
453
|
-
if (!txResponse.ok) continue;
|
|
454
|
-
const txData = await txResponse.json();
|
|
455
|
-
const tx = txData.result;
|
|
506
|
+
const txResp = await solanaRpcCall('getTransaction', [sig.signature, { encoding: 'jsonParsed' }]);
|
|
507
|
+
if (!txResp.ok) continue;
|
|
508
|
+
const tx = txResp.result;
|
|
456
509
|
|
|
457
510
|
if (!tx || !tx.meta) continue;
|
|
458
511
|
|
|
@@ -477,7 +530,7 @@ export async function scanSolanaTrustTransactions(address) {
|
|
|
477
530
|
|
|
478
531
|
return trustTxs;
|
|
479
532
|
} catch (err) {
|
|
480
|
-
console.
|
|
533
|
+
console.warn('Solana trust scan skipped:', err.message || err);
|
|
481
534
|
return [];
|
|
482
535
|
}
|
|
483
536
|
}
|