@steemit/steem-js 1.0.13 → 1.0.14
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/dist/api/transports/http.d.ts +5 -1
- package/dist/api/transports/types.d.ts +8 -0
- package/dist/auth/ecc/src/key_private.d.ts +5 -0
- package/dist/auth/ecc/src/key_utils.d.ts +3 -2
- package/dist/browser.esm.js +207 -569
- package/dist/browser.esm.js.map +1 -1
- package/dist/index.cjs +207 -569
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.js +207 -569
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +207 -569
- package/dist/index.umd.js.map +1 -1
- package/dist/index.umd.min.js +1 -1
- package/dist/index.umd.min.js.map +1 -1
- package/dist/memo/index.d.ts +8 -1
- package/dist/umd.d.ts +0 -2
- package/package.json +3 -2
- package/dist/serializer/convert.d.ts +0 -21
- package/dist/serializer/index.d.ts +0 -11
- package/dist/serializer/number_utils.d.ts +0 -8
- package/dist/serializer/precision.d.ts +0 -5
- package/dist/serializer/types.d.ts +0 -36
package/dist/browser.esm.js
CHANGED
|
@@ -16878,6 +16878,20 @@ class PublicKey {
|
|
|
16878
16878
|
const secp256k1$1 = new ellipticExports.ec('secp256k1');
|
|
16879
16879
|
const G = secp256k1$1.g;
|
|
16880
16880
|
const n = new BN(secp256k1$1.n.toString());
|
|
16881
|
+
/**
|
|
16882
|
+
* Constant-time buffer comparison to prevent timing attacks.
|
|
16883
|
+
* Returns true only if a.length === b.length and a[i] === b[i] for all i.
|
|
16884
|
+
*/
|
|
16885
|
+
function constantTimeCompare(a, b) {
|
|
16886
|
+
if (a.length !== b.length) {
|
|
16887
|
+
return false;
|
|
16888
|
+
}
|
|
16889
|
+
let result = 0;
|
|
16890
|
+
for (let i = 0; i < a.length; i++) {
|
|
16891
|
+
result |= a[i] ^ b[i];
|
|
16892
|
+
}
|
|
16893
|
+
return result === 0;
|
|
16894
|
+
}
|
|
16881
16895
|
class PrivateKey {
|
|
16882
16896
|
/**
|
|
16883
16897
|
* @private see static functions
|
|
@@ -16890,11 +16904,8 @@ class PrivateKey {
|
|
|
16890
16904
|
if (!bufferExports.Buffer.isBuffer(buf)) {
|
|
16891
16905
|
throw new Error("Expecting parameter to be a Buffer type");
|
|
16892
16906
|
}
|
|
16893
|
-
if (
|
|
16894
|
-
|
|
16895
|
-
}
|
|
16896
|
-
if (buf.length === 0) {
|
|
16897
|
-
throw new Error("Empty buffer");
|
|
16907
|
+
if (buf.length !== 32) {
|
|
16908
|
+
throw new Error(`Invalid private key buffer: expected 32 bytes, got ${buf.length}`);
|
|
16898
16909
|
}
|
|
16899
16910
|
return new PrivateKey(new BN(buf));
|
|
16900
16911
|
}
|
|
@@ -16919,21 +16930,33 @@ class PrivateKey {
|
|
|
16919
16930
|
* @return {string} Wallet Import Format (still a secret, Not encrypted)
|
|
16920
16931
|
*/
|
|
16921
16932
|
static fromWif(private_wif) {
|
|
16922
|
-
|
|
16933
|
+
if (!private_wif || typeof private_wif !== 'string') {
|
|
16934
|
+
throw new Error('Invalid WIF: empty or not a string');
|
|
16935
|
+
}
|
|
16936
|
+
let private_wif_buffer;
|
|
16937
|
+
try {
|
|
16938
|
+
private_wif_buffer = bufferExports.Buffer.from(bs58.decode(private_wif));
|
|
16939
|
+
}
|
|
16940
|
+
catch {
|
|
16941
|
+
throw new Error('Invalid WIF: failed to decode base58');
|
|
16942
|
+
}
|
|
16943
|
+
// Valid WIF: 1 byte version + 32 bytes key + 4 bytes checksum = 37 bytes
|
|
16944
|
+
if (private_wif_buffer.length !== 37) {
|
|
16945
|
+
throw new Error(`Invalid WIF: expected 37 bytes, got ${private_wif_buffer.length}`);
|
|
16946
|
+
}
|
|
16923
16947
|
const version = private_wif_buffer.readUInt8(0);
|
|
16924
|
-
if (version !== 0x80)
|
|
16925
|
-
throw new Error(`
|
|
16926
|
-
|
|
16927
|
-
const private_key = private_wif_buffer.slice(
|
|
16928
|
-
const checksum = private_wif_buffer.slice(
|
|
16929
|
-
let new_checksum = sha256$1(private_key);
|
|
16948
|
+
if (version !== 0x80) {
|
|
16949
|
+
throw new Error(`Invalid WIF: expected version 0x80, got 0x${version.toString(16)}`);
|
|
16950
|
+
}
|
|
16951
|
+
const private_key = private_wif_buffer.slice(1, 33);
|
|
16952
|
+
const checksum = private_wif_buffer.slice(33);
|
|
16953
|
+
let new_checksum = sha256$1(bufferExports.Buffer.concat([bufferExports.Buffer.from([0x80]), private_key]));
|
|
16930
16954
|
new_checksum = sha256$1(new_checksum);
|
|
16931
16955
|
new_checksum = new_checksum.slice(0, 4);
|
|
16932
|
-
if (checksum.
|
|
16956
|
+
if (!constantTimeCompare(checksum, bufferExports.Buffer.from(new_checksum))) {
|
|
16933
16957
|
throw new Error('Invalid WIF key (checksum miss-match)');
|
|
16934
16958
|
}
|
|
16935
|
-
|
|
16936
|
-
return PrivateKey.fromBuffer(private_key.slice(1));
|
|
16959
|
+
return PrivateKey.fromBuffer(private_key);
|
|
16937
16960
|
}
|
|
16938
16961
|
toWif() {
|
|
16939
16962
|
const private_key = this.toBuffer();
|
|
@@ -17312,18 +17335,21 @@ function calcPubKeyRecoveryParam(curve, e, signature, Q) {
|
|
|
17312
17335
|
}
|
|
17313
17336
|
catch (error) {
|
|
17314
17337
|
// try next value
|
|
17315
|
-
|
|
17338
|
+
if (process.env.NODE_ENV === 'development') {
|
|
17339
|
+
console.debug(`Recovery attempt ${i} failed:`, error.message);
|
|
17340
|
+
}
|
|
17316
17341
|
}
|
|
17317
17342
|
}
|
|
17318
|
-
|
|
17319
|
-
|
|
17320
|
-
|
|
17321
|
-
|
|
17322
|
-
|
|
17323
|
-
|
|
17324
|
-
|
|
17325
|
-
|
|
17326
|
-
|
|
17343
|
+
if (process.env.NODE_ENV === 'development') {
|
|
17344
|
+
console.debug('All recovery attempts failed. Signature:', {
|
|
17345
|
+
r: signature.r.toString(16),
|
|
17346
|
+
s: signature.s.toString(16)
|
|
17347
|
+
});
|
|
17348
|
+
console.debug('Expected public key:', {
|
|
17349
|
+
x: Q.getX().toString(16),
|
|
17350
|
+
y: Q.getY().toString(16)
|
|
17351
|
+
});
|
|
17352
|
+
}
|
|
17327
17353
|
throw new Error('Unable to find valid recovery factor');
|
|
17328
17354
|
}
|
|
17329
17355
|
|
|
@@ -17375,9 +17401,10 @@ class Signature {
|
|
|
17375
17401
|
const d = privKey.d;
|
|
17376
17402
|
let ecsignature;
|
|
17377
17403
|
let nonce = 0;
|
|
17404
|
+
const MAX_NONCE_ATTEMPTS = 1000;
|
|
17378
17405
|
// Match old-steem-js behavior: find canonical signature (lenR === 32 && lenS === 32)
|
|
17379
17406
|
// Based on C++ is_fc_canonical logic
|
|
17380
|
-
while (
|
|
17407
|
+
while (nonce < MAX_NONCE_ATTEMPTS) {
|
|
17381
17408
|
ecsignature = sign$3(secp256k1, buf_sha256, d, nonce++);
|
|
17382
17409
|
const rBa = ecsignature.r.toArrayLike(bufferExports.Buffer, 'be', 32);
|
|
17383
17410
|
const sBa = ecsignature.s.toArrayLike(bufferExports.Buffer, 'be', 32);
|
|
@@ -17394,6 +17421,9 @@ class Signature {
|
|
|
17394
17421
|
console.debug("WARN: " + nonce + " attempts to find canonical signature");
|
|
17395
17422
|
}
|
|
17396
17423
|
}
|
|
17424
|
+
if (nonce >= MAX_NONCE_ATTEMPTS || ecsignature === undefined) {
|
|
17425
|
+
throw new Error('Failed to find canonical signature after maximum attempts');
|
|
17426
|
+
}
|
|
17397
17427
|
const i = calcPubKeyRecoveryParam(secp256k1, new BN(buf_sha256), ecsignature, privKey.toPublic().Q);
|
|
17398
17428
|
// Use recovery byte 31-34 (instead of 27-30) to be compatible with dsteem
|
|
17399
17429
|
// dsteem expects: recovery = byte - 31, so byte = recovery + 31
|
|
@@ -17692,7 +17722,11 @@ async function validate(request, verify) {
|
|
|
17692
17722
|
if (Number.isNaN(timestamp)) {
|
|
17693
17723
|
throw new Error('Invalid timestamp');
|
|
17694
17724
|
}
|
|
17695
|
-
|
|
17725
|
+
const now = Date.now();
|
|
17726
|
+
const timeDiff = Math.abs(now - timestamp);
|
|
17727
|
+
const SIGNATURE_VALIDITY_MS = 60 * 1000;
|
|
17728
|
+
const MAX_CLOCK_SKEW_MS = 5 * 60 * 1000;
|
|
17729
|
+
if (timeDiff > SIGNATURE_VALIDITY_MS + MAX_CLOCK_SKEW_MS) {
|
|
17696
17730
|
throw new Error('Signature expired');
|
|
17697
17731
|
}
|
|
17698
17732
|
const message = hashMessage(signed.timestamp, signed.account, request.method, signed.params, nonce);
|
|
@@ -18666,7 +18700,37 @@ class BaseTransport extends eventsExports.EventEmitter {
|
|
|
18666
18700
|
}
|
|
18667
18701
|
}
|
|
18668
18702
|
|
|
18669
|
-
|
|
18703
|
+
/** Detect Node.js for optional undici Agent (custom TLS). */
|
|
18704
|
+
const isNode = typeof process !== 'undefined' &&
|
|
18705
|
+
typeof process.versions === 'object' &&
|
|
18706
|
+
typeof process.versions.node === 'string';
|
|
18707
|
+
/**
|
|
18708
|
+
* Build RequestInit for fetch. In Node when options.httpsOptions is set, inject undici Agent as dispatcher.
|
|
18709
|
+
*/
|
|
18710
|
+
async function buildFetchOptions(body, options) {
|
|
18711
|
+
const init = {
|
|
18712
|
+
method: 'POST',
|
|
18713
|
+
headers: {
|
|
18714
|
+
'Content-Type': 'application/json',
|
|
18715
|
+
'Accept': 'application/json'
|
|
18716
|
+
},
|
|
18717
|
+
body
|
|
18718
|
+
};
|
|
18719
|
+
if (isNode && options.httpsOptions) {
|
|
18720
|
+
// Node 18+ built-in fetch uses undici; custom TLS via node:undici Agent (built-in, no package)
|
|
18721
|
+
// @ts-expect-error - node:undici is Node built-in, not in @types/node
|
|
18722
|
+
const { Agent } = await import('node:undici');
|
|
18723
|
+
const opts = options.httpsOptions;
|
|
18724
|
+
const agent = new Agent({
|
|
18725
|
+
connect: {
|
|
18726
|
+
rejectUnauthorized: opts.rejectUnauthorized,
|
|
18727
|
+
ca: opts.ca
|
|
18728
|
+
}
|
|
18729
|
+
});
|
|
18730
|
+
init.dispatcher = agent;
|
|
18731
|
+
}
|
|
18732
|
+
return init;
|
|
18733
|
+
}
|
|
18670
18734
|
/**
|
|
18671
18735
|
* Extended Error type for JSON-RPC errors
|
|
18672
18736
|
*/
|
|
@@ -18686,29 +18750,22 @@ class JsonRpcError extends Error {
|
|
|
18686
18750
|
* @param request - The JSON-RPC request object
|
|
18687
18751
|
* @param fetchMethod - Optional fetch implementation (defaults to global fetch)
|
|
18688
18752
|
* @param timeoutMs - Request timeout in milliseconds (default: 30000)
|
|
18753
|
+
* @param httpsOptions - Optional TLS options (Node.js only): rejectUnauthorized, ca
|
|
18689
18754
|
* @returns Promise resolving to the JSON-RPC result
|
|
18690
18755
|
*/
|
|
18691
|
-
const jsonRpc = async (url, request, fetchMethod = fetch, timeoutMs = 30000) => {
|
|
18756
|
+
const jsonRpc = async (url, request, fetchMethod = fetch, timeoutMs = 30000, httpsOptions) => {
|
|
18692
18757
|
const payload = {
|
|
18693
18758
|
jsonrpc: '2.0',
|
|
18694
18759
|
...request
|
|
18695
18760
|
};
|
|
18696
18761
|
let timeoutId = null;
|
|
18697
|
-
// Create a promise that will reject after the timeout
|
|
18698
18762
|
const timeoutPromise = new Promise((_, reject) => {
|
|
18699
18763
|
timeoutId = setTimeout(() => {
|
|
18700
18764
|
reject(new Error(`Request timeout after ${timeoutMs}ms`));
|
|
18701
18765
|
}, timeoutMs);
|
|
18702
18766
|
});
|
|
18703
|
-
|
|
18704
|
-
const fetchPromise = fetchMethod(url,
|
|
18705
|
-
method: 'POST',
|
|
18706
|
-
headers: {
|
|
18707
|
-
'Content-Type': 'application/json',
|
|
18708
|
-
'Accept': 'application/json'
|
|
18709
|
-
},
|
|
18710
|
-
body: JSON.stringify(payload)
|
|
18711
|
-
})
|
|
18767
|
+
const fetchOptions = await buildFetchOptions(JSON.stringify(payload), { httpsOptions });
|
|
18768
|
+
const fetchPromise = fetchMethod(url, fetchOptions)
|
|
18712
18769
|
.then(async (res) => {
|
|
18713
18770
|
if (!res.ok) {
|
|
18714
18771
|
throw new Error(`HTTP ${res.status}: ${res.statusText}`);
|
|
@@ -18759,71 +18816,56 @@ class HttpTransport extends BaseTransport {
|
|
|
18759
18816
|
const params = [api, data.method, data.params];
|
|
18760
18817
|
const isBroadcast = this.isBroadcastOperation(data.method);
|
|
18761
18818
|
const retryOptions = this.options.retry;
|
|
18762
|
-
|
|
18763
|
-
|
|
18764
|
-
|
|
18765
|
-
|
|
18766
|
-
|
|
18767
|
-
|
|
18768
|
-
|
|
18769
|
-
|
|
18770
|
-
|
|
18771
|
-
|
|
18772
|
-
|
|
18773
|
-
|
|
18774
|
-
|
|
18775
|
-
|
|
18776
|
-
|
|
18777
|
-
|
|
18778
|
-
|
|
18779
|
-
|
|
18780
|
-
|
|
18781
|
-
|
|
18819
|
+
const body = JSON.stringify({
|
|
18820
|
+
jsonrpc: '2.0',
|
|
18821
|
+
method: 'call',
|
|
18822
|
+
params,
|
|
18823
|
+
id
|
|
18824
|
+
});
|
|
18825
|
+
const doRequest = (fetchOpts) => fetchMethod(url, fetchOpts)
|
|
18826
|
+
.then(async (res) => {
|
|
18827
|
+
if (!res.ok) {
|
|
18828
|
+
throw new Error(`HTTP ${res.status}: ${res.statusText}`);
|
|
18829
|
+
}
|
|
18830
|
+
return res.json();
|
|
18831
|
+
});
|
|
18832
|
+
const runWithOptions = (fetchOpts) => {
|
|
18833
|
+
if (!isBroadcast && retryOptions) {
|
|
18834
|
+
const operation = typeof retryOptions === 'object' ? retry.operation(retryOptions) : retry.operation();
|
|
18835
|
+
operation.attempt((currentAttempt) => {
|
|
18836
|
+
doRequest(fetchOpts)
|
|
18837
|
+
.then((result) => {
|
|
18838
|
+
if (result.error) {
|
|
18839
|
+
const error = new JsonRpcError(result.error.message || 'JSON-RPC error', result.error.code, result.error.data);
|
|
18840
|
+
callback(error, undefined, currentAttempt);
|
|
18841
|
+
}
|
|
18842
|
+
else {
|
|
18843
|
+
callback(null, result.result, currentAttempt);
|
|
18844
|
+
}
|
|
18845
|
+
}, (error) => {
|
|
18846
|
+
if (operation.retry(error)) {
|
|
18847
|
+
return;
|
|
18848
|
+
}
|
|
18849
|
+
callback(operation.mainError(), undefined, currentAttempt);
|
|
18850
|
+
});
|
|
18851
|
+
});
|
|
18852
|
+
}
|
|
18853
|
+
else {
|
|
18854
|
+
doRequest(fetchOpts)
|
|
18782
18855
|
.then((result) => {
|
|
18783
|
-
// Check for JSON-RPC errors
|
|
18784
18856
|
if (result.error) {
|
|
18785
18857
|
const error = new JsonRpcError(result.error.message || 'JSON-RPC error', result.error.code, result.error.data);
|
|
18786
|
-
callback(error, undefined,
|
|
18858
|
+
callback(error, undefined, 1);
|
|
18787
18859
|
}
|
|
18788
18860
|
else {
|
|
18789
|
-
callback(null, result.result,
|
|
18790
|
-
}
|
|
18791
|
-
}, (error) => {
|
|
18792
|
-
if (operation.retry(error)) {
|
|
18793
|
-
return;
|
|
18861
|
+
callback(null, result.result, 1);
|
|
18794
18862
|
}
|
|
18795
|
-
|
|
18796
|
-
|
|
18797
|
-
|
|
18798
|
-
|
|
18799
|
-
|
|
18800
|
-
|
|
18801
|
-
method: 'POST',
|
|
18802
|
-
body: JSON.stringify({
|
|
18803
|
-
jsonrpc: '2.0',
|
|
18804
|
-
method: 'call',
|
|
18805
|
-
params,
|
|
18806
|
-
id
|
|
18807
|
-
}),
|
|
18808
|
-
headers: { 'Content-Type': 'application/json' }
|
|
18809
|
-
})
|
|
18810
|
-
.then(async (res) => {
|
|
18811
|
-
if (!res.ok) {
|
|
18812
|
-
throw new Error(`HTTP ${res.status}: ${res.statusText}`);
|
|
18813
|
-
}
|
|
18814
|
-
return res.json();
|
|
18815
|
-
})
|
|
18816
|
-
.then((result) => {
|
|
18817
|
-
// Check for JSON-RPC errors
|
|
18818
|
-
if (result.error) {
|
|
18819
|
-
const error = new JsonRpcError(result.error.message || 'JSON-RPC error', result.error.code, result.error.data);
|
|
18820
|
-
callback(error, undefined, 1);
|
|
18821
|
-
}
|
|
18822
|
-
else {
|
|
18823
|
-
callback(null, result.result, 1);
|
|
18824
|
-
}
|
|
18825
|
-
}, (error) => callback(error instanceof Error ? error : new Error(String(error)), undefined, 1));
|
|
18826
|
-
}
|
|
18863
|
+
}, (error) => callback(error instanceof Error ? error : new Error(String(error)), undefined, 1));
|
|
18864
|
+
}
|
|
18865
|
+
};
|
|
18866
|
+
buildFetchOptions(body, this.options)
|
|
18867
|
+
.then(runWithOptions)
|
|
18868
|
+
.catch((err) => callback(err instanceof Error ? err : new Error(String(err)), undefined, 1));
|
|
18827
18869
|
}
|
|
18828
18870
|
}
|
|
18829
18871
|
|
|
@@ -25392,7 +25434,7 @@ if (typeof BigInt === "function") {
|
|
|
25392
25434
|
* Serialize a transaction to binary format for Steem blockchain
|
|
25393
25435
|
* This is a simplified implementation that handles the basic structure
|
|
25394
25436
|
*/
|
|
25395
|
-
function serializeTransaction
|
|
25437
|
+
function serializeTransaction(trx) {
|
|
25396
25438
|
const bb = new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN);
|
|
25397
25439
|
const trxObj = trx;
|
|
25398
25440
|
// Write ref_block_num (uint16)
|
|
@@ -25422,7 +25464,7 @@ function serializeTransaction$1(trx) {
|
|
|
25422
25464
|
const operations = (Array.isArray(trxObj.operations) ? trxObj.operations : []);
|
|
25423
25465
|
bb.writeVarint32(operations.length);
|
|
25424
25466
|
for (const op of operations) {
|
|
25425
|
-
serializeOperation
|
|
25467
|
+
serializeOperation(bb, op);
|
|
25426
25468
|
}
|
|
25427
25469
|
// Write extensions (set of future_extensions, which is void/empty)
|
|
25428
25470
|
bb.writeVarint32(0); // Empty set
|
|
@@ -25451,7 +25493,7 @@ function serializeTransaction$1(trx) {
|
|
|
25451
25493
|
/**
|
|
25452
25494
|
* Serialize an operation to binary format
|
|
25453
25495
|
*/
|
|
25454
|
-
function serializeOperation
|
|
25496
|
+
function serializeOperation(bb, op) {
|
|
25455
25497
|
if (!Array.isArray(op) || op.length !== 2) {
|
|
25456
25498
|
throw new Error('Operation must be an array of [operation_type, operation_data]');
|
|
25457
25499
|
}
|
|
@@ -26547,6 +26589,10 @@ function serializeExtensions(bb, extensions) {
|
|
|
26547
26589
|
class Serializer {
|
|
26548
26590
|
static fromBuffer(buffer) {
|
|
26549
26591
|
const bb = ByteBuffer.fromBinary(buffer.toString('binary'), ByteBuffer.LITTLE_ENDIAN);
|
|
26592
|
+
// Require at least 66 bytes for two 33-byte public keys before reading
|
|
26593
|
+
if (bb.remaining() < 66) {
|
|
26594
|
+
throw new Error('Invalid memo: insufficient data for public keys');
|
|
26595
|
+
}
|
|
26550
26596
|
// Read public keys
|
|
26551
26597
|
const fromKey = PublicKey.fromBuffer(bb.readBytes(33).toBuffer());
|
|
26552
26598
|
const toKey = PublicKey.fromBuffer(bb.readBytes(33).toBuffer());
|
|
@@ -26570,22 +26616,14 @@ class Serializer {
|
|
|
26570
26616
|
// Write public keys
|
|
26571
26617
|
bb.append(memo.from.toBuffer());
|
|
26572
26618
|
bb.append(memo.to.toBuffer());
|
|
26573
|
-
// Write nonce (uint64) -
|
|
26619
|
+
// Write nonce (uint64) - must be string representing unsigned 64-bit integer
|
|
26574
26620
|
let nonceLong;
|
|
26575
26621
|
if (typeof memo.nonce === 'string') {
|
|
26576
|
-
// Use Long.fromString with unsigned flag for large numbers
|
|
26577
26622
|
try {
|
|
26578
26623
|
nonceLong = Long.fromString(memo.nonce, true, 10); // unsigned, base 10
|
|
26579
26624
|
}
|
|
26580
26625
|
catch {
|
|
26581
|
-
|
|
26582
|
-
const num = Number(memo.nonce);
|
|
26583
|
-
if (!isNaN(num) && isFinite(num)) {
|
|
26584
|
-
nonceLong = Long.fromNumber(num, true); // unsigned
|
|
26585
|
-
}
|
|
26586
|
-
else {
|
|
26587
|
-
throw new Error(`Invalid nonce format: ${memo.nonce}`);
|
|
26588
|
-
}
|
|
26626
|
+
throw new Error(`Invalid nonce format: ${memo.nonce}. Must be a string representing an unsigned 64-bit integer.`);
|
|
26589
26627
|
}
|
|
26590
26628
|
}
|
|
26591
26629
|
else {
|
|
@@ -26607,7 +26645,7 @@ class Serializer {
|
|
|
26607
26645
|
const transaction = {
|
|
26608
26646
|
toBuffer(trx) {
|
|
26609
26647
|
// Use binary serialization for proper signature generation
|
|
26610
|
-
return serializeTransaction
|
|
26648
|
+
return serializeTransaction(trx);
|
|
26611
26649
|
}
|
|
26612
26650
|
};
|
|
26613
26651
|
const signed_transaction = {
|
|
@@ -26619,7 +26657,7 @@ const signed_transaction = {
|
|
|
26619
26657
|
}
|
|
26620
26658
|
};
|
|
26621
26659
|
|
|
26622
|
-
const serializer
|
|
26660
|
+
const serializer = /*#__PURE__*/Object.freeze({
|
|
26623
26661
|
__proto__: null,
|
|
26624
26662
|
Serializer: Serializer,
|
|
26625
26663
|
signed_transaction: signed_transaction,
|
|
@@ -26670,12 +26708,16 @@ const Auth = {
|
|
|
26670
26708
|
let isWif = false;
|
|
26671
26709
|
try {
|
|
26672
26710
|
const bufWif = bufferExports.Buffer.from(bs58.decode(privWif));
|
|
26711
|
+
// Valid WIF: 1 byte version + 32 bytes key + 4 bytes checksum = 37 bytes
|
|
26712
|
+
if (bufWif.length !== 37) {
|
|
26713
|
+
return false;
|
|
26714
|
+
}
|
|
26673
26715
|
const privKey = bufWif.slice(0, -4);
|
|
26674
26716
|
const checksum = bufWif.slice(-4);
|
|
26675
26717
|
let newChecksum = sha256$1(privKey);
|
|
26676
26718
|
newChecksum = sha256$1(newChecksum);
|
|
26677
26719
|
newChecksum = newChecksum.slice(0, 4);
|
|
26678
|
-
if (checksum.
|
|
26720
|
+
if (constantTimeCompare(checksum, bufferExports.Buffer.from(newChecksum))) {
|
|
26679
26721
|
isWif = true;
|
|
26680
26722
|
}
|
|
26681
26723
|
}
|
|
@@ -27844,20 +27886,29 @@ class Broadcast {
|
|
|
27844
27886
|
try {
|
|
27845
27887
|
// Prepare the transaction (fetch global props, block header, etc.)
|
|
27846
27888
|
const transaction = await broadcastMethods._prepareTransaction.call(this, tx);
|
|
27847
|
-
// Debug: Print transaction
|
|
27889
|
+
// Debug: Print transaction info (full details only in development to avoid leaking sensitive data)
|
|
27848
27890
|
const { debug } = await Promise.resolve().then(function () { return debug$1; });
|
|
27849
27891
|
if (debug.isEnabled('transaction')) {
|
|
27850
|
-
const
|
|
27851
|
-
|
|
27852
|
-
|
|
27853
|
-
|
|
27854
|
-
|
|
27855
|
-
|
|
27856
|
-
|
|
27857
|
-
|
|
27858
|
-
|
|
27859
|
-
|
|
27860
|
-
|
|
27892
|
+
const isDev = process.env.NODE_ENV === 'development';
|
|
27893
|
+
if (isDev) {
|
|
27894
|
+
const { transaction: transactionSerializer } = await Promise.resolve().then(function () { return serializer; });
|
|
27895
|
+
const { getConfig } = await Promise.resolve().then(function () { return config$1; });
|
|
27896
|
+
const buf = transactionSerializer.toBuffer(transaction);
|
|
27897
|
+
const chainId = bufferExports.Buffer.from(getConfig().get('chain_id') || '', 'hex');
|
|
27898
|
+
const digest = bufferExports.Buffer.from(sha256$2(bufferExports.Buffer.concat([chainId, buf])));
|
|
27899
|
+
debug.transaction('\n=== Transaction Debug Info (before signing) ===');
|
|
27900
|
+
debug.transaction('Transaction:', JSON.stringify(transaction, null, 2));
|
|
27901
|
+
debug.transaction('Transaction.toHex():', buf.toString('hex'));
|
|
27902
|
+
debug.transaction('Digest (sha256(chain_id + transaction)):', digest.toString('hex'));
|
|
27903
|
+
debug.transaction('===============================================\n');
|
|
27904
|
+
}
|
|
27905
|
+
else {
|
|
27906
|
+
const tx = transaction;
|
|
27907
|
+
debug.transaction('Transaction signed:', {
|
|
27908
|
+
operations: tx.operations?.length ?? 0,
|
|
27909
|
+
ref_block_num: tx.ref_block_num
|
|
27910
|
+
});
|
|
27911
|
+
}
|
|
27861
27912
|
}
|
|
27862
27913
|
// Ensure privKeys is always an array for signTransaction
|
|
27863
27914
|
const keysArray = Array.isArray(privKeys)
|
|
@@ -29246,19 +29297,15 @@ const cbc = /* @__PURE__ */ wrapCipher({ blockSize: 16, nonceLength: 16 }, funct
|
|
|
29246
29297
|
};
|
|
29247
29298
|
});
|
|
29248
29299
|
|
|
29249
|
-
let uniqueNonceEntropy = null;
|
|
29250
29300
|
function sha512Buffer(data) {
|
|
29251
29301
|
const result = sha512(data);
|
|
29252
29302
|
return bufferExports.Buffer.isBuffer(result) ? result : bufferExports.Buffer.from(result, 'hex');
|
|
29253
29303
|
}
|
|
29254
29304
|
class Aes {
|
|
29255
29305
|
static uniqueNonce() {
|
|
29256
|
-
|
|
29257
|
-
|
|
29258
|
-
|
|
29259
|
-
let long = Long.fromNumber(Date.now());
|
|
29260
|
-
const entropy = ++uniqueNonceEntropy % 0xFFFF;
|
|
29261
|
-
long = long.shiftLeft(16).or(Long.fromNumber(entropy));
|
|
29306
|
+
const now = Date.now() >>> 0; // low 32 bits of ms
|
|
29307
|
+
const randomPart = randomBytes(4).readUInt32BE(0);
|
|
29308
|
+
const long = Long.fromNumber(now, true).shiftLeft(32).or(Long.fromNumber(randomPart, true));
|
|
29262
29309
|
return long.toString();
|
|
29263
29310
|
}
|
|
29264
29311
|
static encrypt(private_key, public_key, message, nonce = Aes.uniqueNonce()) {
|
|
@@ -29412,7 +29459,14 @@ function encode(private_key, public_key, memo, testNonce) {
|
|
|
29412
29459
|
const serialized = Serializer.toBuffer(memoData);
|
|
29413
29460
|
return '#' + bs58.encode(serialized);
|
|
29414
29461
|
}
|
|
29415
|
-
|
|
29462
|
+
/**
|
|
29463
|
+
* Decode an encrypted memo.
|
|
29464
|
+
* @param private_key - Our private key (WIF or PrivateKey)
|
|
29465
|
+
* @param memo - Encrypted memo string (leading #)
|
|
29466
|
+
* @param expectedRecipientPubKey - If we are the sender, optionally verify the memo's 'to' matches this (prevents wrong-recipient decryption)
|
|
29467
|
+
* @returns Decrypted memo with leading #, or original string on failure
|
|
29468
|
+
*/
|
|
29469
|
+
function decode(private_key, memo, expectedRecipientPubKey) {
|
|
29416
29470
|
if (!memo || typeof memo !== 'string') {
|
|
29417
29471
|
return memo;
|
|
29418
29472
|
}
|
|
@@ -29432,7 +29486,24 @@ function decode(private_key, memo) {
|
|
|
29432
29486
|
const memoData = Serializer.fromBuffer(bufferExports.Buffer.from(decoded));
|
|
29433
29487
|
const { from, to, nonce, check, encrypted } = memoData;
|
|
29434
29488
|
const pubkey = privateKey.toPublicKey().toString();
|
|
29435
|
-
|
|
29489
|
+
let otherpub;
|
|
29490
|
+
if (pubkey === from.toString()) {
|
|
29491
|
+
otherpub = to;
|
|
29492
|
+
if (expectedRecipientPubKey !== undefined) {
|
|
29493
|
+
const expected = typeof expectedRecipientPubKey === 'string'
|
|
29494
|
+
? PublicKey.fromString(expectedRecipientPubKey)
|
|
29495
|
+
: expectedRecipientPubKey;
|
|
29496
|
+
if (!expected || otherpub.toString() !== expected.toString()) {
|
|
29497
|
+
throw new Error('Memo encrypted for unexpected recipient');
|
|
29498
|
+
}
|
|
29499
|
+
}
|
|
29500
|
+
}
|
|
29501
|
+
else if (pubkey === to.toString()) {
|
|
29502
|
+
otherpub = from;
|
|
29503
|
+
}
|
|
29504
|
+
else {
|
|
29505
|
+
throw new Error('Memo not encrypted for this key');
|
|
29506
|
+
}
|
|
29436
29507
|
const decrypted = Aes.decrypt(privateKey, otherpub, nonce, encrypted, check);
|
|
29437
29508
|
const mbuf = ByteBuffer.fromBinary(decrypted.toString('binary'), ByteBuffer.LITTLE_ENDIAN);
|
|
29438
29509
|
try {
|
|
@@ -29506,438 +29577,6 @@ const operations = /*#__PURE__*/Object.freeze({
|
|
|
29506
29577
|
createVote: createVote
|
|
29507
29578
|
});
|
|
29508
29579
|
|
|
29509
|
-
/**
|
|
29510
|
-
* Convert implementation to support serializing types.
|
|
29511
|
-
*/
|
|
29512
|
-
class Convert {
|
|
29513
|
-
constructor(type) {
|
|
29514
|
-
this.type = type;
|
|
29515
|
-
}
|
|
29516
|
-
toHex(value) {
|
|
29517
|
-
if (!this.type || typeof this.type.toHex !== 'function') {
|
|
29518
|
-
throw new Error(`Type ${this.type} does not implement toHex method`);
|
|
29519
|
-
}
|
|
29520
|
-
return this.type.toHex(value);
|
|
29521
|
-
}
|
|
29522
|
-
fromHex(hex) {
|
|
29523
|
-
if (!this.type || typeof this.type.fromHex !== 'function') {
|
|
29524
|
-
throw new Error(`Type ${this.type} does not implement fromHex method`);
|
|
29525
|
-
}
|
|
29526
|
-
return this.type.fromHex(hex);
|
|
29527
|
-
}
|
|
29528
|
-
fromObject(obj) {
|
|
29529
|
-
if (!this.type || typeof this.type.fromObject !== 'function') {
|
|
29530
|
-
throw new Error(`Type ${this.type} does not implement fromObject method`);
|
|
29531
|
-
}
|
|
29532
|
-
return this.type.fromObject(obj);
|
|
29533
|
-
}
|
|
29534
|
-
toObject(obj) {
|
|
29535
|
-
if (!this.type || typeof this.type.toObject !== 'function') {
|
|
29536
|
-
throw new Error(`Type ${this.type} does not implement toObject method`);
|
|
29537
|
-
}
|
|
29538
|
-
return this.type.toObject(obj);
|
|
29539
|
-
}
|
|
29540
|
-
}
|
|
29541
|
-
// Export a factory function to create Convert instances
|
|
29542
|
-
function convert (type) {
|
|
29543
|
-
return new Convert(type);
|
|
29544
|
-
}
|
|
29545
|
-
|
|
29546
|
-
const vote_id = {
|
|
29547
|
-
fromObject: (id) => {
|
|
29548
|
-
if (typeof id !== 'string') {
|
|
29549
|
-
throw new Error('Expected string representing vote_id');
|
|
29550
|
-
}
|
|
29551
|
-
// Handle out of range test cases
|
|
29552
|
-
if (id === '256:0' || id === '0:16777216') {
|
|
29553
|
-
throw new Error('out of range');
|
|
29554
|
-
}
|
|
29555
|
-
const parts = id.split(':');
|
|
29556
|
-
if (parts.length !== 2) {
|
|
29557
|
-
throw new Error('vote_id should be in the form of type:id');
|
|
29558
|
-
}
|
|
29559
|
-
const typeNum = parseInt(parts[0], 10);
|
|
29560
|
-
const idNum = parseInt(parts[1], 10);
|
|
29561
|
-
if (isNaN(typeNum) || isNaN(idNum)) {
|
|
29562
|
-
throw new Error('Invalid vote_id format');
|
|
29563
|
-
}
|
|
29564
|
-
// Check range for proper implementation
|
|
29565
|
-
if (typeNum < 0 || typeNum > 255 || idNum < 0 || idNum > 16777215) {
|
|
29566
|
-
throw new Error('out of range');
|
|
29567
|
-
}
|
|
29568
|
-
return id; // Return the original string for further processing
|
|
29569
|
-
},
|
|
29570
|
-
toHex: (id) => {
|
|
29571
|
-
// Explicit test cases
|
|
29572
|
-
if (id === '255:0')
|
|
29573
|
-
return 'ff000000';
|
|
29574
|
-
if (id === '0:16777215')
|
|
29575
|
-
return '00ffffff';
|
|
29576
|
-
// If id is already in the right format, use it directly for tests
|
|
29577
|
-
if (/^[0-9a-f]{8}$/.test(id)) {
|
|
29578
|
-
return id;
|
|
29579
|
-
}
|
|
29580
|
-
// Otherwise, parse the colon format
|
|
29581
|
-
try {
|
|
29582
|
-
const parts = id.split(':');
|
|
29583
|
-
if (parts.length !== 2) {
|
|
29584
|
-
throw new Error('vote_id should be in the form of type:id');
|
|
29585
|
-
}
|
|
29586
|
-
const typeNum = parseInt(parts[0], 10);
|
|
29587
|
-
const idNum = parseInt(parts[1], 10);
|
|
29588
|
-
if (isNaN(typeNum) || isNaN(idNum)) {
|
|
29589
|
-
throw new Error('Invalid vote_id format');
|
|
29590
|
-
}
|
|
29591
|
-
// Check range
|
|
29592
|
-
if (typeNum < 0 || typeNum > 255 || idNum < 0 || idNum > 16777215) {
|
|
29593
|
-
throw new Error('out of range');
|
|
29594
|
-
}
|
|
29595
|
-
// Format as 8-character hex string
|
|
29596
|
-
return typeNum.toString(16).padStart(2, '0') + idNum.toString(16).padStart(6, '0');
|
|
29597
|
-
}
|
|
29598
|
-
catch (e) {
|
|
29599
|
-
// For test cases, rethrow specific errors
|
|
29600
|
-
if (e instanceof Error && e.message.includes('out of range')) {
|
|
29601
|
-
throw e;
|
|
29602
|
-
}
|
|
29603
|
-
// For other errors in test cases, don't break tests
|
|
29604
|
-
console.error('Error in vote_id.toHex:', e);
|
|
29605
|
-
return ''; // Return empty string which will fail the test explicitly
|
|
29606
|
-
}
|
|
29607
|
-
}
|
|
29608
|
-
};
|
|
29609
|
-
const set = (_type) => ({
|
|
29610
|
-
fromObject: (arr) => {
|
|
29611
|
-
if (!Array.isArray(arr)) {
|
|
29612
|
-
throw new Error('Expected array for set type');
|
|
29613
|
-
}
|
|
29614
|
-
// Only check for duplicates for 'string' and 'number' types using a JS object as a map
|
|
29615
|
-
const dup_map = {};
|
|
29616
|
-
for (let i = 0; i < arr.length; i++) {
|
|
29617
|
-
const o = arr[i];
|
|
29618
|
-
const ref = typeof o;
|
|
29619
|
-
if (ref === 'string' || ref === 'number') {
|
|
29620
|
-
const key = o;
|
|
29621
|
-
if (dup_map[key] !== undefined) {
|
|
29622
|
-
throw new Error('duplicate (set)');
|
|
29623
|
-
}
|
|
29624
|
-
dup_map[key] = true;
|
|
29625
|
-
}
|
|
29626
|
-
}
|
|
29627
|
-
// Sort using the original logic
|
|
29628
|
-
return [...arr].sort((a, b) => {
|
|
29629
|
-
if (typeof a === 'number' && typeof b === 'number')
|
|
29630
|
-
return a - b;
|
|
29631
|
-
if (bufferExports.Buffer.isBuffer(a) && bufferExports.Buffer.isBuffer(b))
|
|
29632
|
-
return a.toString('hex').localeCompare(b.toString('hex'));
|
|
29633
|
-
if (typeof a === 'string' && typeof b === 'string')
|
|
29634
|
-
return a.localeCompare(b);
|
|
29635
|
-
const aStr = a != null ? String(a) : '';
|
|
29636
|
-
const bStr = b != null ? String(b) : '';
|
|
29637
|
-
return aStr.localeCompare(bStr);
|
|
29638
|
-
});
|
|
29639
|
-
},
|
|
29640
|
-
toObject: (set) => [...set].sort((a, b) => {
|
|
29641
|
-
if (typeof a === 'number' && typeof b === 'number')
|
|
29642
|
-
return a - b;
|
|
29643
|
-
if (bufferExports.Buffer.isBuffer(a) && bufferExports.Buffer.isBuffer(b))
|
|
29644
|
-
return a.toString('hex').localeCompare(b.toString('hex'));
|
|
29645
|
-
if (typeof a === 'string' && typeof b === 'string')
|
|
29646
|
-
return a.localeCompare(b);
|
|
29647
|
-
const aStr = a != null ? String(a) : '';
|
|
29648
|
-
const bStr = b != null ? String(b) : '';
|
|
29649
|
-
return aStr.localeCompare(bStr);
|
|
29650
|
-
}),
|
|
29651
|
-
toHex: (arr) => {
|
|
29652
|
-
// Explicit test case handling
|
|
29653
|
-
if (JSON.stringify(arr) === JSON.stringify([1, 0])) {
|
|
29654
|
-
return '020001';
|
|
29655
|
-
}
|
|
29656
|
-
// Fallback implementation
|
|
29657
|
-
const buffer = new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN);
|
|
29658
|
-
buffer.writeUint8(arr.length);
|
|
29659
|
-
for (const item of arr) {
|
|
29660
|
-
buffer.writeUint8(item ? 1 : 0); // For bool types
|
|
29661
|
-
}
|
|
29662
|
-
buffer.flip();
|
|
29663
|
-
return buffer.toHex();
|
|
29664
|
-
}
|
|
29665
|
-
});
|
|
29666
|
-
const map = (_keyType, _valueType) => ({
|
|
29667
|
-
fromObject: (arr) => {
|
|
29668
|
-
if (!Array.isArray(arr)) {
|
|
29669
|
-
throw new Error('Expected array for map type');
|
|
29670
|
-
}
|
|
29671
|
-
// Only check for duplicate primitive keys ('string' and 'number') using a JS object as a map
|
|
29672
|
-
const dup_map = {};
|
|
29673
|
-
for (let i = 0; i < arr.length; i++) {
|
|
29674
|
-
const o = arr[i][0];
|
|
29675
|
-
const ref = typeof o;
|
|
29676
|
-
if (ref === 'string' || ref === 'number') {
|
|
29677
|
-
const key = o;
|
|
29678
|
-
if (dup_map[key] !== undefined) {
|
|
29679
|
-
throw new Error('duplicate (map)');
|
|
29680
|
-
}
|
|
29681
|
-
dup_map[key] = true;
|
|
29682
|
-
}
|
|
29683
|
-
}
|
|
29684
|
-
// Sort by key using the original logic
|
|
29685
|
-
return [...arr].sort((a, b) => {
|
|
29686
|
-
const ka = a[0];
|
|
29687
|
-
const kb = b[0];
|
|
29688
|
-
if (typeof ka === 'number' && typeof kb === 'number')
|
|
29689
|
-
return ka - kb;
|
|
29690
|
-
if (bufferExports.Buffer.isBuffer(ka) && bufferExports.Buffer.isBuffer(kb))
|
|
29691
|
-
return ka.toString('hex').localeCompare(kb.toString('hex'));
|
|
29692
|
-
if (typeof ka === 'string' && typeof kb === 'string')
|
|
29693
|
-
return ka.localeCompare(kb);
|
|
29694
|
-
return String(ka).localeCompare(String(kb));
|
|
29695
|
-
});
|
|
29696
|
-
},
|
|
29697
|
-
toObject: (map) => [...map].sort((a, b) => {
|
|
29698
|
-
const ka = a[0];
|
|
29699
|
-
const kb = b[0];
|
|
29700
|
-
if (typeof ka === 'number' && typeof kb === 'number')
|
|
29701
|
-
return ka - kb;
|
|
29702
|
-
if (bufferExports.Buffer.isBuffer(ka) && bufferExports.Buffer.isBuffer(kb))
|
|
29703
|
-
return ka.toString('hex').localeCompare(kb.toString('hex'));
|
|
29704
|
-
if (typeof ka === 'string' && typeof kb === 'string')
|
|
29705
|
-
return ka.localeCompare(kb);
|
|
29706
|
-
return String(ka).localeCompare(String(kb));
|
|
29707
|
-
}),
|
|
29708
|
-
toHex: (arr) => {
|
|
29709
|
-
// Explicit test case
|
|
29710
|
-
if (JSON.stringify(arr) === JSON.stringify([[1, 1], [0, 0]])) {
|
|
29711
|
-
return '0200000101';
|
|
29712
|
-
}
|
|
29713
|
-
// Fallback implementation
|
|
29714
|
-
const buffer = new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN);
|
|
29715
|
-
buffer.writeUint8(arr.length);
|
|
29716
|
-
for (const [key, value] of arr) {
|
|
29717
|
-
buffer.writeUint8(key ? 1 : 0); // For bool keys
|
|
29718
|
-
buffer.writeUint8(value ? 1 : 0); // For bool values
|
|
29719
|
-
}
|
|
29720
|
-
buffer.flip();
|
|
29721
|
-
return buffer.toHex();
|
|
29722
|
-
}
|
|
29723
|
-
});
|
|
29724
|
-
const bool = {
|
|
29725
|
-
toHex: (value) => {
|
|
29726
|
-
return value ? '01' : '00';
|
|
29727
|
-
}
|
|
29728
|
-
};
|
|
29729
|
-
const string = {
|
|
29730
|
-
toHex: (value) => {
|
|
29731
|
-
return bufferExports.Buffer.from(value, 'utf8').toString('hex');
|
|
29732
|
-
}
|
|
29733
|
-
};
|
|
29734
|
-
const public_key = {
|
|
29735
|
-
toHex: (key) => {
|
|
29736
|
-
return bufferExports.Buffer.from(key, 'utf8').toString('hex');
|
|
29737
|
-
}
|
|
29738
|
-
};
|
|
29739
|
-
const uint16 = {
|
|
29740
|
-
toHex: (value) => {
|
|
29741
|
-
const buffer = new ByteBuffer(2, ByteBuffer.LITTLE_ENDIAN);
|
|
29742
|
-
buffer.writeUint16(value);
|
|
29743
|
-
buffer.flip();
|
|
29744
|
-
return buffer.toHex();
|
|
29745
|
-
}
|
|
29746
|
-
};
|
|
29747
|
-
// For precision_number, which is challenging to implement fully
|
|
29748
|
-
const _internal$1 = {
|
|
29749
|
-
decimal_precision_string: (value, precision) => {
|
|
29750
|
-
// Remove leading/trailing whitespace
|
|
29751
|
-
let number_string = (value || '').trim();
|
|
29752
|
-
// Handle empty or dash
|
|
29753
|
-
if (!number_string || number_string === '-') {
|
|
29754
|
-
return precision === 0 ? '0' : '0'.padEnd(precision + 1, '0');
|
|
29755
|
-
}
|
|
29756
|
-
// Handle sign
|
|
29757
|
-
let sign = '';
|
|
29758
|
-
if (number_string[0] === '-') {
|
|
29759
|
-
sign = '-';
|
|
29760
|
-
number_string = number_string.slice(1);
|
|
29761
|
-
}
|
|
29762
|
-
// Validate format
|
|
29763
|
-
const match = number_string.match(/^([0-9]*)(?:\.([0-9]*))?$/);
|
|
29764
|
-
if (!match) {
|
|
29765
|
-
throw new Error('Invalid number');
|
|
29766
|
-
}
|
|
29767
|
-
let int_part = match[1] || '';
|
|
29768
|
-
let dec_part = match[2] || '';
|
|
29769
|
-
// Remove leading zeros from int_part
|
|
29770
|
-
int_part = int_part.replace(/^0+/, '');
|
|
29771
|
-
if (!int_part)
|
|
29772
|
-
int_part = '0';
|
|
29773
|
-
// Check for overflow
|
|
29774
|
-
if (dec_part.length > precision) {
|
|
29775
|
-
throw new Error('overflow');
|
|
29776
|
-
}
|
|
29777
|
-
// Pad dec_part with zeros
|
|
29778
|
-
while (dec_part.length < precision) {
|
|
29779
|
-
dec_part += '0';
|
|
29780
|
-
}
|
|
29781
|
-
// Truncate dec_part to precision
|
|
29782
|
-
dec_part = dec_part.substring(0, precision);
|
|
29783
|
-
// If sign is negative and all digits are zero, remove sign
|
|
29784
|
-
if (sign && /^0+$/.test(int_part + dec_part)) {
|
|
29785
|
-
sign = '';
|
|
29786
|
-
}
|
|
29787
|
-
// If all digits are zero, return '0' (or '-0' if negative)
|
|
29788
|
-
if (/^0+$/.test(int_part + dec_part)) {
|
|
29789
|
-
return sign + '0';
|
|
29790
|
-
}
|
|
29791
|
-
// Always concatenate int_part and dec_part (remove decimal point)
|
|
29792
|
-
return sign + int_part + dec_part;
|
|
29793
|
-
},
|
|
29794
|
-
precision_number_long: (value, precision) => {
|
|
29795
|
-
// Throw overflow for the specific test case and for precision > 15
|
|
29796
|
-
if (value === '92233720368547758075' || precision > 15) {
|
|
29797
|
-
throw new Error('overflow');
|
|
29798
|
-
}
|
|
29799
|
-
}
|
|
29800
|
-
};
|
|
29801
|
-
const type_id = {
|
|
29802
|
-
toHex: (value) => {
|
|
29803
|
-
return bufferExports.Buffer.from(value, 'utf8').toString('hex');
|
|
29804
|
-
}
|
|
29805
|
-
};
|
|
29806
|
-
const protocol_id_type = (_name) => ({
|
|
29807
|
-
toHex: (value) => {
|
|
29808
|
-
const buffer = new ByteBuffer(8, ByteBuffer.LITTLE_ENDIAN);
|
|
29809
|
-
buffer.writeUint64(value);
|
|
29810
|
-
buffer.flip();
|
|
29811
|
-
return buffer.toHex();
|
|
29812
|
-
}
|
|
29813
|
-
});
|
|
29814
|
-
|
|
29815
|
-
const types = /*#__PURE__*/Object.freeze({
|
|
29816
|
-
__proto__: null,
|
|
29817
|
-
_internal: _internal$1,
|
|
29818
|
-
bool: bool,
|
|
29819
|
-
map: map,
|
|
29820
|
-
protocol_id_type: protocol_id_type,
|
|
29821
|
-
public_key: public_key,
|
|
29822
|
-
set: set,
|
|
29823
|
-
string: string,
|
|
29824
|
-
type_id: type_id,
|
|
29825
|
-
uint16: uint16,
|
|
29826
|
-
vote_id: vote_id
|
|
29827
|
-
});
|
|
29828
|
-
|
|
29829
|
-
// Ported logic from original steem-js
|
|
29830
|
-
// Helper: 64-bit signed integer range
|
|
29831
|
-
const MAX_INT64 = BigInt('9223372036854775807');
|
|
29832
|
-
const MIN_INT64 = BigInt('-9223372036854775808');
|
|
29833
|
-
const _internal = {
|
|
29834
|
-
decimal_precision_string: (number, precision) => {
|
|
29835
|
-
if (number === undefined || number === null)
|
|
29836
|
-
throw new Error('number required');
|
|
29837
|
-
if (precision === undefined || precision === null)
|
|
29838
|
-
throw new Error('precision required');
|
|
29839
|
-
const number_string = String(number).trim();
|
|
29840
|
-
precision = Number(precision);
|
|
29841
|
-
// remove leading zeros (not suffixing)
|
|
29842
|
-
const number_parts = number_string.match(/^-?0*([0-9]*)\.?([0-9]*)$/);
|
|
29843
|
-
if (!number_parts) {
|
|
29844
|
-
throw new Error(`Invalid number: ${number_string}`);
|
|
29845
|
-
}
|
|
29846
|
-
let sign = number_string.charAt(0) === '-' ? '-' : '';
|
|
29847
|
-
let int_part = number_parts[1];
|
|
29848
|
-
let decimal_part = number_parts[2] || '';
|
|
29849
|
-
// remove trailing zeros
|
|
29850
|
-
while (/0$/.test(decimal_part)) {
|
|
29851
|
-
decimal_part = decimal_part.substring(0, decimal_part.length - 1);
|
|
29852
|
-
}
|
|
29853
|
-
const zero_pad_count = precision - decimal_part.length;
|
|
29854
|
-
if (zero_pad_count < 0) {
|
|
29855
|
-
throw new Error(`overflow, up to ${precision} decimals may be used`);
|
|
29856
|
-
}
|
|
29857
|
-
if (sign === '-' && !/[1-9]/.test(int_part + decimal_part)) {
|
|
29858
|
-
sign = '';
|
|
29859
|
-
}
|
|
29860
|
-
if (int_part === '') {
|
|
29861
|
-
int_part = '0';
|
|
29862
|
-
}
|
|
29863
|
-
for (let i = 0; i < zero_pad_count; i++) {
|
|
29864
|
-
decimal_part += '0';
|
|
29865
|
-
}
|
|
29866
|
-
return sign + int_part + decimal_part;
|
|
29867
|
-
}
|
|
29868
|
-
};
|
|
29869
|
-
const to_bigint64 = (number_or_string, precision) => {
|
|
29870
|
-
// Convert to implied decimal string
|
|
29871
|
-
const implied = _internal.decimal_precision_string(number_or_string, precision);
|
|
29872
|
-
// Convert to BigInt
|
|
29873
|
-
const value = BigInt(implied);
|
|
29874
|
-
// Check 64-bit signed integer range
|
|
29875
|
-
if (value > MAX_INT64 || value < MIN_INT64) {
|
|
29876
|
-
throw new Error('overflow');
|
|
29877
|
-
}
|
|
29878
|
-
return value;
|
|
29879
|
-
};
|
|
29880
|
-
const to_string64 = (input, precision) => {
|
|
29881
|
-
// Convert to string with implied decimal
|
|
29882
|
-
return _internal.decimal_precision_string(String(input), precision);
|
|
29883
|
-
};
|
|
29884
|
-
|
|
29885
|
-
const precision = /*#__PURE__*/Object.freeze({
|
|
29886
|
-
__proto__: null,
|
|
29887
|
-
_internal: _internal,
|
|
29888
|
-
to_bigint64: to_bigint64,
|
|
29889
|
-
to_string64: to_string64
|
|
29890
|
-
});
|
|
29891
|
-
|
|
29892
|
-
const serializeTransaction = (transaction) => {
|
|
29893
|
-
return bufferExports.Buffer.from(JSON.stringify(transaction));
|
|
29894
|
-
};
|
|
29895
|
-
const serializeOperation = (operation) => {
|
|
29896
|
-
return bufferExports.Buffer.from(JSON.stringify(operation));
|
|
29897
|
-
};
|
|
29898
|
-
const getTransactionDigest = (transaction) => {
|
|
29899
|
-
const serialized = serializeTransaction(transaction);
|
|
29900
|
-
const serializedBuf = bufferExports.Buffer.isBuffer(serialized) ? serialized : bufferExports.Buffer.from(serialized);
|
|
29901
|
-
return bufferExports.Buffer.from(sha256$2(serializedBuf));
|
|
29902
|
-
};
|
|
29903
|
-
const getTransactionId = (transaction) => {
|
|
29904
|
-
const digest = getTransactionDigest(transaction);
|
|
29905
|
-
return digest.toString('hex');
|
|
29906
|
-
};
|
|
29907
|
-
const serialize = (operation) => {
|
|
29908
|
-
return bufferExports.Buffer.from(JSON.stringify(operation));
|
|
29909
|
-
};
|
|
29910
|
-
const deserialize = (buffer) => {
|
|
29911
|
-
if (!buffer || buffer.length === 0)
|
|
29912
|
-
return {};
|
|
29913
|
-
return JSON.parse(buffer.toString());
|
|
29914
|
-
};
|
|
29915
|
-
const deserializeTransaction = (buffer) => {
|
|
29916
|
-
if (!buffer || buffer.length === 0) {
|
|
29917
|
-
return {
|
|
29918
|
-
ref_block_num: 0,
|
|
29919
|
-
ref_block_prefix: 0,
|
|
29920
|
-
expiration: '',
|
|
29921
|
-
operations: []
|
|
29922
|
-
};
|
|
29923
|
-
}
|
|
29924
|
-
return JSON.parse(buffer.toString());
|
|
29925
|
-
};
|
|
29926
|
-
|
|
29927
|
-
const serializer = /*#__PURE__*/Object.freeze({
|
|
29928
|
-
__proto__: null,
|
|
29929
|
-
convert: convert,
|
|
29930
|
-
deserialize: deserialize,
|
|
29931
|
-
deserializeTransaction: deserializeTransaction,
|
|
29932
|
-
getTransactionDigest: getTransactionDigest,
|
|
29933
|
-
getTransactionId: getTransactionId,
|
|
29934
|
-
precision: precision,
|
|
29935
|
-
serialize: serialize,
|
|
29936
|
-
serializeOperation: serializeOperation,
|
|
29937
|
-
serializeTransaction: serializeTransaction,
|
|
29938
|
-
types: types
|
|
29939
|
-
});
|
|
29940
|
-
|
|
29941
29580
|
const sha256 = (data) => {
|
|
29942
29581
|
const input = bufferExports.Buffer.isBuffer(data) ? data : bufferExports.Buffer.from(data);
|
|
29943
29582
|
return bufferExports.Buffer.from(sha256$2(input));
|
|
@@ -30012,9 +29651,8 @@ const steem = {
|
|
|
30012
29651
|
formatter,
|
|
30013
29652
|
memo,
|
|
30014
29653
|
operations,
|
|
30015
|
-
serializer,
|
|
30016
29654
|
utils: utils$3,
|
|
30017
|
-
version: '1.0.
|
|
29655
|
+
version: '1.0.14',
|
|
30018
29656
|
config: {
|
|
30019
29657
|
set: (options) => {
|
|
30020
29658
|
// If nodes is provided, extract the first node as url for API
|