blue-js-sdk 2.0.3 → 2.1.1
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/ai-path/cli.js +13 -0
- package/ai-path/connect.js +34 -2
- package/ai-path/index.js +5 -0
- package/batch.js +2 -2
- package/chain/broadcast.js +113 -3
- package/chain/queries.js +21 -0
- package/connection/connect.js +22 -7
- package/docs/CHAIN-PROTOCOL-UPGRADE-PROPOSAL.md +662 -0
- package/docs/ON-CHAIN-FUNCTIONS.md +1310 -0
- package/index.js +12 -0
- package/package.json +2 -1
- package/plan-operations.js +18 -11
- package/protocol/encoding.js +38 -24
- package/protocol/messages.js +19 -19
- package/protocol/plans.js +18 -11
- package/protocol/v3.js +11 -7
- package/test-subscription-flows.js +457 -0
- package/v3protocol.js +38 -24
- package/test-all-chain-ops.js +0 -493
- package/test-feegrant-connect.js +0 -98
- package/test-logic.js +0 -148
package/test-logic.js
DELETED
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Pure logic tests — matches Go's 45 tests exactly.
|
|
4
|
-
* NO chain calls, NO network, NO tokens. Instant and safe.
|
|
5
|
-
*/
|
|
6
|
-
import {
|
|
7
|
-
formatP2P, formatPriceP2P, formatNodePricing, estimateSessionPrice,
|
|
8
|
-
formatBytes, formatUptime, shortAddress, computeSessionAllocation,
|
|
9
|
-
countryNameToCode, getFlagUrl, getFlagEmoji,
|
|
10
|
-
GB_OPTIONS, HOUR_OPTIONS,
|
|
11
|
-
DNS_PRESETS, DEFAULT_DNS_PRESET, DNS_FALLBACK_ORDER, resolveDnsServers,
|
|
12
|
-
ErrorCodes, ERROR_SEVERITY, isRetryable, userMessage,
|
|
13
|
-
APP_TYPES, APP_TYPE_CONFIG, validateAppConfig,
|
|
14
|
-
cached, cacheInvalidate, diskSave, diskLoad,
|
|
15
|
-
trackSession, getSessionMode, loadAppSettings, APP_SETTINGS_DEFAULTS,
|
|
16
|
-
} from './index.js';
|
|
17
|
-
|
|
18
|
-
let pass = 0, fail = 0;
|
|
19
|
-
function t(name, result) {
|
|
20
|
-
if (result) { pass++; }
|
|
21
|
-
else { fail++; console.log(' ✗', name); }
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
console.log('═══ HELPERS (19 tests) ═══');
|
|
25
|
-
// FormatP2P
|
|
26
|
-
t('formatP2P 40152030', formatP2P(40152030) === '40.15 P2P');
|
|
27
|
-
t('formatP2P 1000000', formatP2P(1000000) === '1.00 P2P');
|
|
28
|
-
t('formatP2P 0', formatP2P(0) === '0.00 P2P');
|
|
29
|
-
|
|
30
|
-
// FormatPriceP2P
|
|
31
|
-
t('formatPriceP2P 40152030', formatPriceP2P(40152030) === '40.15');
|
|
32
|
-
t('formatPriceP2P string', formatPriceP2P('1000000') === '1.00');
|
|
33
|
-
|
|
34
|
-
// FormatBytes
|
|
35
|
-
t('formatBytes 1.5GB', formatBytes(1500000000).includes('GB'));
|
|
36
|
-
t('formatBytes 250MB', formatBytes(250000000).includes('MB'));
|
|
37
|
-
t('formatBytes 1000', formatBytes(1000) === '1000 B' || formatBytes(1000).includes('KB'));
|
|
38
|
-
t('formatBytes 0', formatBytes(0) === '0 B');
|
|
39
|
-
|
|
40
|
-
// FormatUptime
|
|
41
|
-
t('formatUptime 2h2m', formatUptime(7350000) === '2h 2m');
|
|
42
|
-
t('formatUptime 1m30s', formatUptime(90000) === '1m 30s');
|
|
43
|
-
t('formatUptime 45s', formatUptime(45000) === '45s');
|
|
44
|
-
t('formatUptime 0', formatUptime(0) === '0s');
|
|
45
|
-
|
|
46
|
-
// ShortAddress
|
|
47
|
-
t('shortAddress', shortAddress('sent1example9pqrse8q4m6lz8alxqv5hkx3fkxe0q', 12, 6).includes('...'));
|
|
48
|
-
|
|
49
|
-
// ComputeAllocation GB-based
|
|
50
|
-
const allocGb = computeSessionAllocation({ downloadBytes: '500000000', uploadBytes: '100000000', maxBytes: '1000000000', max_duration: '0s' });
|
|
51
|
-
t('allocation GB percent', allocGb.usedPercent === 60);
|
|
52
|
-
t('allocation GB isGbBased', allocGb.isGbBased === true);
|
|
53
|
-
|
|
54
|
-
// ComputeAllocation hourly
|
|
55
|
-
const allocHr = computeSessionAllocation({ downloadBytes: '100000', uploadBytes: '50000', maxBytes: '1000000000', max_duration: '3600s' });
|
|
56
|
-
t('allocation hourly', allocHr.isHourlyBased === true);
|
|
57
|
-
|
|
58
|
-
// Options
|
|
59
|
-
t('GB_OPTIONS has 1 and 50', GB_OPTIONS.includes(1) && GB_OPTIONS.includes(50));
|
|
60
|
-
t('HOUR_OPTIONS has 1 and 24', HOUR_OPTIONS.includes(1) && HOUR_OPTIONS.includes(24));
|
|
61
|
-
|
|
62
|
-
console.log('═══ COUNTRY & FLAGS (13 tests) ═══');
|
|
63
|
-
t('Netherlands → NL', countryNameToCode('The Netherlands') === 'NL');
|
|
64
|
-
t('Türkiye → TR', countryNameToCode('Türkiye') === 'TR');
|
|
65
|
-
t('DR Congo → CD', countryNameToCode('DR Congo') === 'CD');
|
|
66
|
-
t('Czechia → CZ', countryNameToCode('Czechia') === 'CZ');
|
|
67
|
-
t('Russian Federation → RU', countryNameToCode('Russian Federation') === 'RU');
|
|
68
|
-
t('Viet Nam → VN', countryNameToCode('Viet Nam') === 'VN');
|
|
69
|
-
t('South Korea → KR', countryNameToCode('South Korea') === 'KR');
|
|
70
|
-
t('UAE → AE', countryNameToCode('UAE') === 'AE');
|
|
71
|
-
t('us → US', countryNameToCode('us') === 'US');
|
|
72
|
-
t('Atlantis → null', countryNameToCode('Atlantis') === null);
|
|
73
|
-
t('empty → null', countryNameToCode('') === null);
|
|
74
|
-
t('getFlagUrl US', getFlagUrl('US').includes('flagcdn.com'));
|
|
75
|
-
t('getFlagEmoji DE', getFlagEmoji('DE') === '🇩🇪');
|
|
76
|
-
|
|
77
|
-
console.log('═══ DNS (11 tests) ═══');
|
|
78
|
-
t('default is handshake', DEFAULT_DNS_PRESET === 'handshake');
|
|
79
|
-
t('3 presets', Object.keys(DNS_PRESETS).length === 3);
|
|
80
|
-
t('fallback order 3', DNS_FALLBACK_ORDER.length === 3);
|
|
81
|
-
t('resolve default has handshake', resolveDnsServers().includes('103.196.38.38'));
|
|
82
|
-
t('resolve default has google fallback', resolveDnsServers().includes('8.8.8.8'));
|
|
83
|
-
t('resolve default has cloudflare fallback', resolveDnsServers().includes('1.1.1.1'));
|
|
84
|
-
t('resolve google starts with 8.8.8.8', resolveDnsServers('google').startsWith('8.8.8.8'));
|
|
85
|
-
t('resolve google has handshake fallback', resolveDnsServers('google').includes('103.196.38.38'));
|
|
86
|
-
t('resolve cloudflare starts with 1.1.1.1', resolveDnsServers('cloudflare').startsWith('1.1.1.1'));
|
|
87
|
-
t('resolve custom has fallbacks', resolveDnsServers('9.9.9.9').includes('103.196.38.38'));
|
|
88
|
-
const dnsServers = resolveDnsServers().split(', ');
|
|
89
|
-
t('no duplicate DNS servers', dnsServers.length === new Set(dnsServers).size);
|
|
90
|
-
|
|
91
|
-
console.log('═══ ERRORS (15 tests) ═══');
|
|
92
|
-
const allCodes = Object.values(ErrorCodes);
|
|
93
|
-
t('33 error codes', allCodes.length === 33);
|
|
94
|
-
t('all have user messages', allCodes.every(c => userMessage(c) !== 'An unexpected error occurred.'));
|
|
95
|
-
t('unknown code → default', userMessage('FAKE_CODE') === 'An unexpected error occurred.');
|
|
96
|
-
t('INSUFFICIENT_BALANCE is fatal', ERROR_SEVERITY[ErrorCodes.INSUFFICIENT_BALANCE] === 'fatal');
|
|
97
|
-
t('NODE_OFFLINE is retryable', ERROR_SEVERITY[ErrorCodes.NODE_OFFLINE] === 'retryable');
|
|
98
|
-
t('SESSION_EXISTS is recoverable', ERROR_SEVERITY[ErrorCodes.SESSION_EXISTS] === 'recoverable');
|
|
99
|
-
t('V2RAY_NOT_FOUND is infrastructure', ERROR_SEVERITY[ErrorCodes.V2RAY_NOT_FOUND] === 'infrastructure');
|
|
100
|
-
t('isRetryable NODE_OFFLINE', isRetryable(ErrorCodes.NODE_OFFLINE) === true);
|
|
101
|
-
t('isRetryable INVALID_MNEMONIC', isRetryable(ErrorCodes.INVALID_MNEMONIC) === false);
|
|
102
|
-
t('userMessage INSUFFICIENT_BALANCE', userMessage(ErrorCodes.INSUFFICIENT_BALANCE).includes('P2P'));
|
|
103
|
-
t('userMessage NODE_OFFLINE', userMessage(ErrorCodes.NODE_OFFLINE).includes('offline'));
|
|
104
|
-
t('userMessage V2RAY_NOT_FOUND', userMessage(ErrorCodes.V2RAY_NOT_FOUND).includes('V2Ray'));
|
|
105
|
-
t('userMessage ABORTED', userMessage(ErrorCodes.ABORTED).includes('cancelled'));
|
|
106
|
-
t('userMessage INVALID_ASSIGNED_IP', userMessage(ErrorCodes.INVALID_ASSIGNED_IP).includes('invalid'));
|
|
107
|
-
t('userMessage CHAIN_LAG', userMessage(ErrorCodes.CHAIN_LAG).includes('confirmed'));
|
|
108
|
-
|
|
109
|
-
console.log('═══ APP TYPES (6 tests) ═══');
|
|
110
|
-
t('3 app types', Object.keys(APP_TYPES).length === 3);
|
|
111
|
-
t('WHITE_LABEL exists', APP_TYPES.WHITE_LABEL === 'white_label');
|
|
112
|
-
t('DIRECT_P2P exists', APP_TYPES.DIRECT_P2P === 'direct_p2p');
|
|
113
|
-
t('validate valid', validateAppConfig('white_label', { planId: 42, mnemonic: 'x' }).valid === true);
|
|
114
|
-
t('validate invalid', validateAppConfig('white_label', {}).valid === false);
|
|
115
|
-
t('validate bad type', validateAppConfig('fake', {}).valid === false);
|
|
116
|
-
|
|
117
|
-
console.log('═══ CACHE & SETTINGS (6 tests) ═══');
|
|
118
|
-
const v1 = await cached('logic-test', 5000, async () => 42);
|
|
119
|
-
const v2 = await cached('logic-test', 5000, async () => 99);
|
|
120
|
-
t('cached returns first', v1 === 42 && v2 === 42);
|
|
121
|
-
cacheInvalidate('logic-test');
|
|
122
|
-
const v3 = await cached('logic-test', 5000, async () => 77);
|
|
123
|
-
t('cache invalidate works', v3 === 77);
|
|
124
|
-
diskSave('logic-test-rt', { x: 1 });
|
|
125
|
-
t('diskSave + diskLoad', diskLoad('logic-test-rt', 60000)?.data?.x === 1);
|
|
126
|
-
trackSession('99999', 'hour');
|
|
127
|
-
t('trackSession', getSessionMode('99999') === 'hour');
|
|
128
|
-
const settings = loadAppSettings();
|
|
129
|
-
t('default settings', settings.dnsPreset === 'handshake' && settings.fullTunnel === true);
|
|
130
|
-
t('APP_SETTINGS_DEFAULTS', APP_SETTINGS_DEFAULTS.statusPollSec === 3);
|
|
131
|
-
|
|
132
|
-
// ═══ PRICING (5 tests) ═══
|
|
133
|
-
console.log('═══ PRICING (5 tests) ═══');
|
|
134
|
-
const mockNode = {
|
|
135
|
-
gigabyte_prices: [{ denom: 'udvpn', quote_value: '40152030' }],
|
|
136
|
-
hourly_prices: [{ denom: 'udvpn', quote_value: '18384000' }],
|
|
137
|
-
};
|
|
138
|
-
const pricing = formatNodePricing(mockNode);
|
|
139
|
-
t('formatNodePricing perGb', pricing.perGb?.includes('P2P/GB'));
|
|
140
|
-
t('formatNodePricing perHour', pricing.perHour?.includes('P2P/hr'));
|
|
141
|
-
t('formatNodePricing cheapest', pricing.cheapest === 'hour');
|
|
142
|
-
const gbCost = estimateSessionPrice(mockNode, 'gb', 5);
|
|
143
|
-
t('estimateSessionPrice gb', gbCost.costUdvpn > 0);
|
|
144
|
-
const hrCost = estimateSessionPrice(mockNode, 'hour', 4);
|
|
145
|
-
t('estimateSessionPrice hour', hrCost.costUdvpn > 0);
|
|
146
|
-
|
|
147
|
-
console.log(`\n═══ RESULTS: ${pass} passed, ${fail} failed (${pass + fail} total) ═══`);
|
|
148
|
-
process.exit(fail > 0 ? 1 : 0);
|