@steemit/steem-js 1.0.12 → 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.
@@ -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 (32 !== buf.length) {
16894
- debug.warn(`WARN: Expecting 32 bytes, instead got ${buf.length}, stack trace:`, new Error().stack);
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
- const private_wif_buffer = bufferExports.Buffer.from(bs58.decode(private_wif));
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(`Expected version ${0x80}, instead got ${version}`);
16926
- // checksum includes the version
16927
- const private_key = private_wif_buffer.slice(0, -4);
16928
- const checksum = private_wif_buffer.slice(-4);
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.toString() !== new_checksum.toString()) {
16956
+ if (!constantTimeCompare(checksum, bufferExports.Buffer.from(new_checksum))) {
16933
16957
  throw new Error('Invalid WIF key (checksum miss-match)');
16934
16958
  }
16935
- private_key.writeUInt8(0x80, 0);
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
- console.debug(`Recovery attempt ${i} failed:`, error.message);
17338
+ if (process.env.NODE_ENV === 'development') {
17339
+ console.debug(`Recovery attempt ${i} failed:`, error.message);
17340
+ }
17316
17341
  }
17317
17342
  }
17318
- // Additional debugging
17319
- console.debug('All recovery attempts failed. Signature:', {
17320
- r: signature.r.toString(16),
17321
- s: signature.s.toString(16)
17322
- });
17323
- console.debug('Expected public key:', {
17324
- x: Q.getX().toString(16),
17325
- y: Q.getY().toString(16)
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 (true) {
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
- if (Date.now() - timestamp > 60 * 1000) {
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
- // @ts-expect-error: No types for 'retry'
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
- // Create the fetch promise
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
- // Note: timeout handling is done via AbortController in jsonRpc function
18763
- if (!isBroadcast && retryOptions) {
18764
- const operation = typeof retryOptions === 'object' ? retry.operation(retryOptions) : retry.operation();
18765
- operation.attempt((currentAttempt) => {
18766
- fetchMethod(url, {
18767
- method: 'POST',
18768
- body: JSON.stringify({
18769
- jsonrpc: '2.0',
18770
- method: 'call',
18771
- params,
18772
- id
18773
- }),
18774
- headers: { 'Content-Type': 'application/json' },
18775
- })
18776
- .then(async (res) => {
18777
- if (!res.ok) {
18778
- throw new Error(`HTTP ${res.status}: ${res.statusText}`);
18779
- }
18780
- return res.json();
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, currentAttempt);
18858
+ callback(error, undefined, 1);
18787
18859
  }
18788
18860
  else {
18789
- callback(null, result.result, currentAttempt);
18790
- }
18791
- }, (error) => {
18792
- if (operation.retry(error)) {
18793
- return;
18861
+ callback(null, result.result, 1);
18794
18862
  }
18795
- callback(operation.mainError(), undefined, currentAttempt);
18796
- });
18797
- });
18798
- }
18799
- else {
18800
- fetchMethod(url, {
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$1(trx) {
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$1(bb, op);
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$1(bb, op) {
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
  }
@@ -25483,9 +25525,45 @@ function getOperationTypeIndex(opType) {
25483
25525
  'account_witness_proxy': 13,
25484
25526
  'pow': 14,
25485
25527
  'custom': 15,
25528
+ 'report_over_production': 16,
25486
25529
  'delete_comment': 17,
25487
25530
  'custom_json': 18,
25488
25531
  'comment_options': 19,
25532
+ 'set_withdraw_vesting_route': 20,
25533
+ 'limit_order_create2': 21,
25534
+ 'claim_account': 22,
25535
+ 'create_claimed_account': 23,
25536
+ 'request_account_recovery': 24,
25537
+ 'recover_account': 25,
25538
+ 'change_recovery_account': 26,
25539
+ 'escrow_transfer': 27,
25540
+ 'escrow_dispute': 28,
25541
+ 'escrow_release': 29,
25542
+ 'pow2': 30,
25543
+ 'escrow_approve': 31,
25544
+ 'transfer_to_savings': 32,
25545
+ 'transfer_from_savings': 33,
25546
+ 'cancel_transfer_from_savings': 34,
25547
+ 'custom_binary': 35,
25548
+ 'decline_voting_rights': 36,
25549
+ 'reset_account': 37,
25550
+ 'set_reset_account': 38,
25551
+ 'claim_reward_balance': 39,
25552
+ 'delegate_vesting_shares': 40,
25553
+ 'account_create_with_delegation': 41,
25554
+ 'witness_set_properties': 42,
25555
+ 'account_update2': 43,
25556
+ 'create_proposal': 44,
25557
+ 'update_proposal_votes': 45,
25558
+ 'remove_proposal': 46,
25559
+ 'claim_reward_balance2': 47,
25560
+ 'fill_convert_request': 48,
25561
+ 'comment_reward': 49,
25562
+ 'liquidity_reward': 50,
25563
+ 'interest': 51,
25564
+ 'fill_vesting_withdraw': 52,
25565
+ 'fill_order': 53,
25566
+ 'fill_transfer_from_savings': 54,
25489
25567
  };
25490
25568
  const index = opMap[opType];
25491
25569
  if (index === undefined) {
@@ -25510,6 +25588,135 @@ function serializeOperationData(bb, opType, opData) {
25510
25588
  case 'account_create':
25511
25589
  serializeAccountCreate(bb, opData);
25512
25590
  break;
25591
+ case 'account_update':
25592
+ serializeAccountUpdate(bb, opData);
25593
+ break;
25594
+ case 'account_create_with_delegation':
25595
+ serializeAccountCreateWithDelegation(bb, opData);
25596
+ break;
25597
+ case 'create_claimed_account':
25598
+ serializeCreateClaimedAccount(bb, opData);
25599
+ break;
25600
+ case 'account_update2':
25601
+ serializeAccountUpdate2(bb, opData);
25602
+ break;
25603
+ case 'request_account_recovery':
25604
+ serializeRequestAccountRecovery(bb, opData);
25605
+ break;
25606
+ case 'recover_account':
25607
+ serializeRecoverAccount(bb, opData);
25608
+ break;
25609
+ case 'change_recovery_account':
25610
+ serializeChangeRecoveryAccount(bb, opData);
25611
+ break;
25612
+ case 'reset_account':
25613
+ serializeResetAccount(bb, opData);
25614
+ break;
25615
+ case 'set_reset_account':
25616
+ serializeSetResetAccount(bb, opData);
25617
+ break;
25618
+ case 'decline_voting_rights':
25619
+ serializeDeclineVotingRights(bb, opData);
25620
+ break;
25621
+ case 'transfer_to_vesting':
25622
+ serializeTransferToVesting(bb, opData);
25623
+ break;
25624
+ case 'withdraw_vesting':
25625
+ serializeWithdrawVesting(bb, opData);
25626
+ break;
25627
+ case 'set_withdraw_vesting_route':
25628
+ serializeSetWithdrawVestingRoute(bb, opData);
25629
+ break;
25630
+ case 'transfer_to_savings':
25631
+ serializeTransferToSavings(bb, opData);
25632
+ break;
25633
+ case 'transfer_from_savings':
25634
+ serializeTransferFromSavings(bb, opData);
25635
+ break;
25636
+ case 'cancel_transfer_from_savings':
25637
+ serializeCancelTransferFromSavings(bb, opData);
25638
+ break;
25639
+ case 'limit_order_create':
25640
+ serializeLimitOrderCreate(bb, opData);
25641
+ break;
25642
+ case 'limit_order_create2':
25643
+ serializeLimitOrderCreate2(bb, opData);
25644
+ break;
25645
+ case 'limit_order_cancel':
25646
+ serializeLimitOrderCancel(bb, opData);
25647
+ break;
25648
+ case 'feed_publish':
25649
+ serializeFeedPublish(bb, opData);
25650
+ break;
25651
+ case 'convert':
25652
+ serializeConvert(bb, opData);
25653
+ break;
25654
+ case 'fill_order':
25655
+ serializeFillOrder(bb, opData);
25656
+ break;
25657
+ case 'escrow_transfer':
25658
+ serializeEscrowTransfer(bb, opData);
25659
+ break;
25660
+ case 'escrow_dispute':
25661
+ serializeEscrowDispute(bb, opData);
25662
+ break;
25663
+ case 'escrow_release':
25664
+ serializeEscrowRelease(bb, opData);
25665
+ break;
25666
+ case 'escrow_approve':
25667
+ serializeEscrowApprove(bb, opData);
25668
+ break;
25669
+ case 'claim_reward_balance':
25670
+ serializeClaimRewardBalance(bb, opData);
25671
+ break;
25672
+ case 'claim_reward_balance2':
25673
+ serializeClaimRewardBalance2(bb, opData);
25674
+ break;
25675
+ case 'comment_reward':
25676
+ serializeCommentReward(bb, opData);
25677
+ break;
25678
+ case 'liquidity_reward':
25679
+ serializeLiquidityReward(bb, opData);
25680
+ break;
25681
+ case 'interest':
25682
+ serializeInterest(bb, opData);
25683
+ break;
25684
+ case 'fill_vesting_withdraw':
25685
+ serializeFillVestingWithdraw(bb, opData);
25686
+ break;
25687
+ case 'fill_convert_request':
25688
+ serializeFillConvertRequest(bb, opData);
25689
+ break;
25690
+ case 'fill_transfer_from_savings':
25691
+ serializeFillTransferFromSavings(bb, opData);
25692
+ break;
25693
+ case 'pow':
25694
+ serializePow(bb, opData);
25695
+ break;
25696
+ case 'pow2':
25697
+ serializePow2(bb, opData);
25698
+ break;
25699
+ case 'witness_update':
25700
+ serializeWitnessUpdate(bb, opData);
25701
+ break;
25702
+ case 'witness_set_properties':
25703
+ serializeWitnessSetProperties(bb, opData);
25704
+ break;
25705
+ case 'account_witness_vote':
25706
+ serializeAccountWitnessVote(bb, opData);
25707
+ break;
25708
+ case 'account_witness_proxy':
25709
+ serializeAccountWitnessProxy(bb, opData);
25710
+ break;
25711
+ case 'custom':
25712
+ serializeCustom(bb, opData);
25713
+ break;
25714
+ case 'custom_binary':
25715
+ serializeCustomBinary(bb, opData);
25716
+ break;
25717
+ case 'comment_options':
25718
+ serializeCommentOptions(bb, opData);
25719
+ break;
25513
25720
  case 'custom_json':
25514
25721
  serializeCustomJson(bb, opData);
25515
25722
  break;
@@ -25580,143 +25787,843 @@ function serializeAccountCreate(bb, data) {
25580
25787
  writeString(bb, String(dataObj.json_metadata || ''));
25581
25788
  }
25582
25789
  /**
25583
- * Serialize custom_json operation
25790
+ * Serialize account_update operation.
25791
+ * Format: account, optional owner (1 byte + authority?), optional active, optional posting, memo_key, json_metadata.
25584
25792
  */
25585
- function serializeCustomJson(bb, data) {
25793
+ function serializeAccountUpdate(bb, data) {
25586
25794
  const dataObj = data;
25587
- // Serialize required_auths (flat_set<account_name_type>)
25588
- // Set serialization: varint32 length, then each element
25589
- const requiredAuths = Array.isArray(dataObj.required_auths)
25590
- ? dataObj.required_auths.slice().sort()
25591
- : [];
25592
- bb.writeVarint32(requiredAuths.length);
25593
- for (const account of requiredAuths) {
25594
- writeString(bb, String(account));
25795
+ writeString(bb, String(dataObj.account || ''));
25796
+ // Optional authorities: 0 = not present, 1 = present then serialize authority
25797
+ if (dataObj.owner != null && dataObj.owner !== '') {
25798
+ bb.writeUint8(1);
25799
+ serializeAuthority(bb, typeof dataObj.owner === 'object' ? dataObj.owner : { weight_threshold: 1, account_auths: [], key_auths: [] });
25595
25800
  }
25596
- // Serialize required_posting_auths (flat_set<account_name_type>)
25597
- const requiredPostingAuths = Array.isArray(dataObj.required_posting_auths)
25598
- ? dataObj.required_posting_auths.slice().sort()
25599
- : [];
25600
- bb.writeVarint32(requiredPostingAuths.length);
25601
- for (const account of requiredPostingAuths) {
25602
- writeString(bb, String(account));
25801
+ else {
25802
+ bb.writeUint8(0);
25603
25803
  }
25604
- // Serialize id (string)
25605
- writeString(bb, String(dataObj.id || ''));
25606
- // Serialize json (string)
25607
- writeString(bb, String(dataObj.json || '{}'));
25804
+ if (dataObj.active != null && dataObj.active !== '') {
25805
+ bb.writeUint8(1);
25806
+ serializeAuthority(bb, typeof dataObj.active === 'object' ? dataObj.active : { weight_threshold: 1, account_auths: [], key_auths: [] });
25807
+ }
25808
+ else {
25809
+ bb.writeUint8(0);
25810
+ }
25811
+ if (dataObj.posting != null && dataObj.posting !== '') {
25812
+ bb.writeUint8(1);
25813
+ serializeAuthority(bb, typeof dataObj.posting === 'object' ? dataObj.posting : { weight_threshold: 1, account_auths: [], key_auths: [] });
25814
+ }
25815
+ else {
25816
+ bb.writeUint8(0);
25817
+ }
25818
+ // memo_key (public key, required)
25819
+ if (typeof dataObj.memo_key === 'string') {
25820
+ const pubKey = PublicKey.fromStringOrThrow(dataObj.memo_key);
25821
+ bb.append(pubKey.toBuffer());
25822
+ }
25823
+ else if (bufferExports.Buffer.isBuffer(dataObj.memo_key)) {
25824
+ bb.append(dataObj.memo_key);
25825
+ }
25826
+ else if (dataObj.memo_key && typeof dataObj.memo_key.toBuffer === 'function') {
25827
+ bb.append(dataObj.memo_key.toBuffer());
25828
+ }
25829
+ else {
25830
+ throw new Error('Invalid memo_key format');
25831
+ }
25832
+ writeString(bb, typeof dataObj.json_metadata === 'string'
25833
+ ? dataObj.json_metadata
25834
+ : dataObj.json_metadata != null
25835
+ ? JSON.stringify(dataObj.json_metadata)
25836
+ : '');
25608
25837
  }
25609
25838
  /**
25610
- * Serialize Authority
25839
+ * Serialize account_create_with_delegation operation.
25840
+ * Fields (see FC_REFLECT): fee, delegation, creator, new_account_name,
25841
+ * owner, active, posting, memo_key, json_metadata, extensions.
25611
25842
  */
25612
- function serializeAuthority(bb, auth) {
25613
- const authObj = auth;
25614
- bb.writeUint32(authObj.weight_threshold || 1);
25615
- // Account auths (map<string, uint16>)
25616
- const accountAuths = (Array.isArray(authObj.account_auths) ? authObj.account_auths : []);
25617
- // Maps in Steem serialization are sorted by key
25618
- const accountAuthsArray = accountAuths;
25619
- accountAuthsArray.sort((a, b) => {
25620
- const aKey = Array.isArray(a) && a[0] ? String(a[0]) : '';
25621
- const bKey = Array.isArray(b) && b[0] ? String(b[0]) : '';
25622
- return aKey.localeCompare(bKey);
25623
- });
25624
- bb.writeVarint32(accountAuths.length);
25625
- for (const authEntry of accountAuths) {
25626
- if (Array.isArray(authEntry) && authEntry.length >= 2) {
25627
- writeString(bb, String(authEntry[0]));
25628
- bb.writeUint16(authEntry[1]);
25629
- }
25630
- }
25631
- // Key auths (map<public_key, uint16>)
25632
- const keyAuths = (Array.isArray(authObj.key_auths) ? authObj.key_auths : []);
25633
- // Maps in Steem serialization are sorted by key (public key string)
25634
- // But serialized as bytes. Usually sorting by string representation of public key works.
25635
- const keyAuthsArray = keyAuths;
25636
- keyAuthsArray.sort((a, b) => {
25637
- const aKey = Array.isArray(a) && a[0] ? String(a[0]) : '';
25638
- const bKey = Array.isArray(b) && b[0] ? String(b[0]) : '';
25639
- return aKey.localeCompare(bKey);
25640
- });
25641
- bb.writeVarint32(keyAuths.length);
25642
- for (const keyAuth of keyAuths) {
25643
- if (Array.isArray(keyAuth) && keyAuth.length >= 2) {
25644
- const keyStr = String(keyAuth[0]);
25645
- const weight = keyAuth[1];
25646
- const pubKey = PublicKey.fromStringOrThrow(keyStr);
25647
- bb.append(pubKey.toBuffer());
25648
- bb.writeUint16(weight);
25649
- }
25650
- }
25843
+ function serializeAccountCreateWithDelegation(bb, data) {
25844
+ const dataObj = data;
25845
+ serializeAsset(bb, String(dataObj.fee || '0.000 STEEM'));
25846
+ serializeAsset(bb, String(dataObj.delegation || '0.000 VESTS'));
25847
+ writeString(bb, String(dataObj.creator || ''));
25848
+ writeString(bb, String(dataObj.new_account_name || ''));
25849
+ serializeAuthority(bb, dataObj.owner);
25850
+ serializeAuthority(bb, dataObj.active);
25851
+ serializeAuthority(bb, dataObj.posting);
25852
+ const memoKey = String(dataObj.memo_key || '');
25853
+ const pubKey = PublicKey.fromStringOrThrow(memoKey);
25854
+ bb.append(pubKey.toBuffer());
25855
+ writeString(bb, String(dataObj.json_metadata || ''));
25856
+ serializeExtensions(bb, dataObj.extensions);
25651
25857
  }
25652
25858
  /**
25653
- * Serialize asset (simplified)
25859
+ * Serialize create_claimed_account operation.
25860
+ * Fields: creator, new_account_name, owner, active, posting,
25861
+ * memo_key, json_metadata, extensions.
25654
25862
  */
25655
- function serializeAsset(bb, amount) {
25656
- const parts = amount.split(' ');
25657
- const valueStr = parts[0] || '0.000';
25658
- const symbol = parts[1] || 'STEEM';
25659
- const [intPart, decPart = ''] = valueStr.split('.');
25660
- const precision = decPart.length;
25661
- const amountValue = parseInt(intPart + decPart.padEnd(precision, '0'), 10) || 0;
25662
- // ByteBuffer can accept number directly for small values
25663
- bb.writeInt64(amountValue);
25664
- bb.writeUint8(precision);
25665
- const symbolBytes = bufferExports.Buffer.from(symbol, 'utf8');
25666
- bb.append(symbolBytes);
25667
- for (let i = symbolBytes.length; i < 7; i++) {
25668
- bb.writeUint8(0);
25669
- }
25863
+ function serializeCreateClaimedAccount(bb, data) {
25864
+ const dataObj = data;
25865
+ writeString(bb, String(dataObj.creator || ''));
25866
+ writeString(bb, String(dataObj.new_account_name || ''));
25867
+ serializeAuthority(bb, dataObj.owner);
25868
+ serializeAuthority(bb, dataObj.active);
25869
+ serializeAuthority(bb, dataObj.posting);
25870
+ const memoKey = String(dataObj.memo_key || '');
25871
+ const pubKey = PublicKey.fromStringOrThrow(memoKey);
25872
+ bb.append(pubKey.toBuffer());
25873
+ writeString(bb, String(dataObj.json_metadata || ''));
25874
+ serializeExtensions(bb, dataObj.extensions);
25670
25875
  }
25671
25876
  /**
25672
- * Write a string using ByteBuffer's writeVString method
25877
+ * Serialize account_update2 operation.
25878
+ * Fields: account, owner, active, posting, memo_key,
25879
+ * json_metadata, posting_json_metadata, extensions.
25673
25880
  */
25674
- function writeString(bb, str) {
25675
- bb.writeVString(str);
25881
+ function serializeAccountUpdate2(bb, data) {
25882
+ const dataObj = data;
25883
+ writeString(bb, String(dataObj.account || ''));
25884
+ serializeAuthority(bb, dataObj.owner);
25885
+ serializeAuthority(bb, dataObj.active);
25886
+ serializeAuthority(bb, dataObj.posting);
25887
+ const memoKey = String(dataObj.memo_key || '');
25888
+ const pubKey = PublicKey.fromStringOrThrow(memoKey);
25889
+ bb.append(pubKey.toBuffer());
25890
+ writeString(bb, String(dataObj.json_metadata || ''));
25891
+ writeString(bb, String(dataObj.posting_json_metadata || ''));
25892
+ serializeExtensions(bb, dataObj.extensions);
25676
25893
  }
25677
-
25678
- class Serializer {
25679
- static fromBuffer(buffer) {
25680
- const bb = ByteBuffer.fromBinary(buffer.toString('binary'), ByteBuffer.LITTLE_ENDIAN);
25681
- // Read public keys
25682
- const fromKey = PublicKey.fromBuffer(bb.readBytes(33).toBuffer());
25683
- const toKey = PublicKey.fromBuffer(bb.readBytes(33).toBuffer());
25684
- // Read nonce (uint64)
25685
- const nonce = bb.readUint64().toString();
25686
- // Read checksum (uint32)
25687
- const check = bb.readUint32();
25688
- // Read encrypted data
25689
- const encryptedLength = bb.readVarint32();
25690
- const encrypted = bb.readBytes(encryptedLength).toString('hex');
25691
- return {
25692
- from: fromKey,
25693
- to: toKey,
25694
- nonce,
25695
- check,
25696
- encrypted
25697
- };
25698
- }
25699
- static toBuffer(memo) {
25700
- const bb = new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN);
25701
- // Write public keys
25702
- bb.append(memo.from.toBuffer());
25703
- bb.append(memo.to.toBuffer());
25704
- // Write nonce (uint64) - handle both string and number
25705
- let nonceLong;
25706
- if (typeof memo.nonce === 'string') {
25707
- // Use Long.fromString with unsigned flag for large numbers
25708
- try {
25894
+ /**
25895
+ * Serialize request_account_recovery operation.
25896
+ * Fields: recovery_account, account_to_recover, new_owner_authority, extensions.
25897
+ */
25898
+ function serializeRequestAccountRecovery(bb, data) {
25899
+ const dataObj = data;
25900
+ writeString(bb, String(dataObj.recovery_account || ''));
25901
+ writeString(bb, String(dataObj.account_to_recover || ''));
25902
+ serializeAuthority(bb, dataObj.new_owner_authority);
25903
+ serializeExtensions(bb, dataObj.extensions);
25904
+ }
25905
+ /**
25906
+ * Serialize recover_account operation.
25907
+ * Fields: account_to_recover, new_owner_authority, recent_owner_authority, extensions.
25908
+ */
25909
+ function serializeRecoverAccount(bb, data) {
25910
+ const dataObj = data;
25911
+ writeString(bb, String(dataObj.account_to_recover || ''));
25912
+ serializeAuthority(bb, dataObj.new_owner_authority);
25913
+ serializeAuthority(bb, dataObj.recent_owner_authority);
25914
+ serializeExtensions(bb, dataObj.extensions);
25915
+ }
25916
+ /**
25917
+ * Serialize change_recovery_account operation.
25918
+ * Fields: account_to_recover, new_recovery_account, extensions.
25919
+ */
25920
+ function serializeChangeRecoveryAccount(bb, data) {
25921
+ const dataObj = data;
25922
+ writeString(bb, String(dataObj.account_to_recover || ''));
25923
+ writeString(bb, String(dataObj.new_recovery_account || ''));
25924
+ serializeExtensions(bb, dataObj.extensions);
25925
+ }
25926
+ /**
25927
+ * Serialize reset_account operation.
25928
+ * Fields: reset_account, account_to_reset, new_owner_authority.
25929
+ */
25930
+ function serializeResetAccount(bb, data) {
25931
+ const dataObj = data;
25932
+ writeString(bb, String(dataObj.reset_account || ''));
25933
+ writeString(bb, String(dataObj.account_to_reset || ''));
25934
+ serializeAuthority(bb, dataObj.new_owner_authority);
25935
+ }
25936
+ /**
25937
+ * Serialize set_reset_account operation.
25938
+ * Fields: account, reset_account.
25939
+ */
25940
+ function serializeSetResetAccount(bb, data) {
25941
+ const dataObj = data;
25942
+ writeString(bb, String(dataObj.account || ''));
25943
+ writeString(bb, String(dataObj.reset_account || ''));
25944
+ }
25945
+ /**
25946
+ * Serialize decline_voting_rights operation.
25947
+ * Fields: account, decline.
25948
+ */
25949
+ function serializeDeclineVotingRights(bb, data) {
25950
+ const dataObj = data;
25951
+ writeString(bb, String(dataObj.account || ''));
25952
+ serializeBool(bb, dataObj.decline);
25953
+ }
25954
+ /**
25955
+ * Serialize transfer_to_vesting operation.
25956
+ * Fields: from, to, amount.
25957
+ */
25958
+ function serializeTransferToVesting(bb, data) {
25959
+ const dataObj = data;
25960
+ writeString(bb, String(dataObj.from || ''));
25961
+ writeString(bb, String(dataObj.to || ''));
25962
+ serializeAsset(bb, String(dataObj.amount || '0.000 STEEM'));
25963
+ }
25964
+ /**
25965
+ * Serialize withdraw_vesting operation.
25966
+ * Fields: account, vesting_shares.
25967
+ */
25968
+ function serializeWithdrawVesting(bb, data) {
25969
+ const dataObj = data;
25970
+ writeString(bb, String(dataObj.account || ''));
25971
+ serializeAsset(bb, String(dataObj.vesting_shares || '0.000 VESTS'));
25972
+ }
25973
+ /**
25974
+ * Serialize set_withdraw_vesting_route operation.
25975
+ * Fields: from_account, to_account, percent, auto_vest.
25976
+ */
25977
+ function serializeSetWithdrawVestingRoute(bb, data) {
25978
+ const dataObj = data;
25979
+ writeString(bb, String(dataObj.from_account || ''));
25980
+ writeString(bb, String(dataObj.to_account || ''));
25981
+ // percent is uint16
25982
+ bb.writeUint16(dataObj.percent ?? 0);
25983
+ serializeBool(bb, dataObj.auto_vest);
25984
+ }
25985
+ /**
25986
+ * Serialize transfer_to_savings operation.
25987
+ * Fields: from, to, amount, memo.
25988
+ */
25989
+ function serializeTransferToSavings(bb, data) {
25990
+ const dataObj = data;
25991
+ writeString(bb, String(dataObj.from || ''));
25992
+ writeString(bb, String(dataObj.to || ''));
25993
+ serializeAsset(bb, String(dataObj.amount || '0.000 STEEM'));
25994
+ writeString(bb, String(dataObj.memo || ''));
25995
+ }
25996
+ /**
25997
+ * Serialize transfer_from_savings operation.
25998
+ * Fields: from, request_id, to, amount, memo.
25999
+ */
26000
+ function serializeTransferFromSavings(bb, data) {
26001
+ const dataObj = data;
26002
+ writeString(bb, String(dataObj.from || ''));
26003
+ bb.writeUint32(dataObj.request_id ?? dataObj.requestID ?? 0);
26004
+ writeString(bb, String(dataObj.to || ''));
26005
+ serializeAsset(bb, String(dataObj.amount || '0.000 STEEM'));
26006
+ writeString(bb, String(dataObj.memo || ''));
26007
+ }
26008
+ /**
26009
+ * Serialize cancel_transfer_from_savings operation.
26010
+ * Fields: from, request_id.
26011
+ */
26012
+ function serializeCancelTransferFromSavings(bb, data) {
26013
+ const dataObj = data;
26014
+ writeString(bb, String(dataObj.from || ''));
26015
+ bb.writeUint32(dataObj.request_id ?? dataObj.requestID ?? 0);
26016
+ }
26017
+ /**
26018
+ * Serialize limit_order_create operation.
26019
+ * Fields: owner, orderid, amount_to_sell, min_to_receive, fill_or_kill, expiration.
26020
+ */
26021
+ function serializeLimitOrderCreate(bb, data) {
26022
+ const dataObj = data;
26023
+ writeString(bb, String(dataObj.owner || ''));
26024
+ bb.writeUint32(dataObj.orderid ?? 0);
26025
+ serializeAsset(bb, String(dataObj.amount_to_sell || '0.000 STEEM'));
26026
+ serializeAsset(bb, String(dataObj.min_to_receive || '0.000 STEEM'));
26027
+ serializeBool(bb, dataObj.fill_or_kill);
26028
+ serializeTimePointSec(bb, dataObj.expiration);
26029
+ }
26030
+ /**
26031
+ * Serialize limit_order_create2 operation.
26032
+ * Fields: owner, orderid, amount_to_sell, exchange_rate{base, quote}, fill_or_kill, expiration.
26033
+ */
26034
+ function serializeLimitOrderCreate2(bb, data) {
26035
+ const dataObj = data;
26036
+ writeString(bb, String(dataObj.owner || ''));
26037
+ bb.writeUint32(dataObj.orderid ?? 0);
26038
+ serializeAsset(bb, String(dataObj.amount_to_sell || '0.000 STEEM'));
26039
+ const rate = (dataObj.exchange_rate ?? dataObj.exchangeRate);
26040
+ const base = rate?.base ?? '0.000 STEEM';
26041
+ const quote = rate?.quote ?? '0.000 SBD';
26042
+ serializeAsset(bb, String(base));
26043
+ serializeAsset(bb, String(quote));
26044
+ serializeBool(bb, dataObj.fill_or_kill);
26045
+ serializeTimePointSec(bb, dataObj.expiration);
26046
+ }
26047
+ /**
26048
+ * Serialize limit_order_cancel operation.
26049
+ * Fields: owner, orderid.
26050
+ */
26051
+ function serializeLimitOrderCancel(bb, data) {
26052
+ const dataObj = data;
26053
+ writeString(bb, String(dataObj.owner || ''));
26054
+ bb.writeUint32(dataObj.orderid ?? 0);
26055
+ }
26056
+ /**
26057
+ * Serialize feed_publish operation.
26058
+ * Fields: publisher, exchange_rate{base, quote}.
26059
+ */
26060
+ function serializeFeedPublish(bb, data) {
26061
+ const dataObj = data;
26062
+ writeString(bb, String(dataObj.publisher || ''));
26063
+ const rate = (dataObj.exchange_rate ?? dataObj.exchangeRate);
26064
+ const base = rate?.base ?? '0.000 STEEM';
26065
+ const quote = rate?.quote ?? '0.000 SBD';
26066
+ serializeAsset(bb, String(base));
26067
+ serializeAsset(bb, String(quote));
26068
+ }
26069
+ /**
26070
+ * Serialize convert operation.
26071
+ * Fields: owner, requestid, amount.
26072
+ */
26073
+ function serializeConvert(bb, data) {
26074
+ const dataObj = data;
26075
+ writeString(bb, String(dataObj.owner || ''));
26076
+ bb.writeUint32(dataObj.requestid ?? dataObj.request_id ?? 0);
26077
+ serializeAsset(bb, String(dataObj.amount || '0.000 STEEM'));
26078
+ }
26079
+ /**
26080
+ * Serialize fill_order operation (virtual).
26081
+ * Fields: current_owner, current_orderid, current_pays,
26082
+ * open_owner, open_orderid, open_pays.
26083
+ */
26084
+ function serializeFillOrder(bb, data) {
26085
+ const dataObj = data;
26086
+ writeString(bb, String(dataObj.current_owner || ''));
26087
+ bb.writeUint32(dataObj.current_orderid ?? 0);
26088
+ serializeAsset(bb, String(dataObj.current_pays || '0.000 STEEM'));
26089
+ writeString(bb, String(dataObj.open_owner || ''));
26090
+ bb.writeUint32(dataObj.open_orderid ?? 0);
26091
+ serializeAsset(bb, String(dataObj.open_pays || '0.000 STEEM'));
26092
+ }
26093
+ /**
26094
+ * Serialize escrow_transfer operation.
26095
+ * Fields: from, to, sbd_amount, steem_amount, escrow_id, agent,
26096
+ * fee, json_meta, ratification_deadline, escrow_expiration.
26097
+ */
26098
+ function serializeEscrowTransfer(bb, data) {
26099
+ const dataObj = data;
26100
+ writeString(bb, String(dataObj.from || ''));
26101
+ writeString(bb, String(dataObj.to || ''));
26102
+ serializeAsset(bb, String(dataObj.sbd_amount || '0.000 SBD'));
26103
+ serializeAsset(bb, String(dataObj.steem_amount || '0.000 STEEM'));
26104
+ bb.writeUint32(dataObj.escrow_id ?? 0);
26105
+ writeString(bb, String(dataObj.agent || ''));
26106
+ serializeAsset(bb, String(dataObj.fee || '0.000 STEEM'));
26107
+ writeString(bb, String(dataObj.json_meta || ''));
26108
+ serializeTimePointSec(bb, dataObj.ratification_deadline);
26109
+ serializeTimePointSec(bb, dataObj.escrow_expiration);
26110
+ }
26111
+ /**
26112
+ * Serialize escrow_dispute operation.
26113
+ * Fields: from, to, who, escrow_id.
26114
+ */
26115
+ function serializeEscrowDispute(bb, data) {
26116
+ const dataObj = data;
26117
+ writeString(bb, String(dataObj.from || ''));
26118
+ writeString(bb, String(dataObj.to || ''));
26119
+ writeString(bb, String(dataObj.who || ''));
26120
+ bb.writeUint32(dataObj.escrow_id ?? 0);
26121
+ }
26122
+ /**
26123
+ * Serialize escrow_release operation.
26124
+ * Fields: from, to, who, escrow_id, sbd_amount, steem_amount.
26125
+ */
26126
+ function serializeEscrowRelease(bb, data) {
26127
+ const dataObj = data;
26128
+ writeString(bb, String(dataObj.from || ''));
26129
+ writeString(bb, String(dataObj.to || ''));
26130
+ writeString(bb, String(dataObj.who || ''));
26131
+ bb.writeUint32(dataObj.escrow_id ?? 0);
26132
+ serializeAsset(bb, String(dataObj.sbd_amount || '0.000 SBD'));
26133
+ serializeAsset(bb, String(dataObj.steem_amount || '0.000 STEEM'));
26134
+ }
26135
+ /**
26136
+ * Serialize escrow_approve operation.
26137
+ * Fields: from, to, agent, who, escrow_id, approve.
26138
+ */
26139
+ function serializeEscrowApprove(bb, data) {
26140
+ const dataObj = data;
26141
+ writeString(bb, String(dataObj.from || ''));
26142
+ writeString(bb, String(dataObj.to || ''));
26143
+ writeString(bb, String(dataObj.agent || ''));
26144
+ writeString(bb, String(dataObj.who || ''));
26145
+ bb.writeUint32(dataObj.escrow_id ?? 0);
26146
+ serializeBool(bb, dataObj.approve);
26147
+ }
26148
+ /**
26149
+ * Serialize claim_reward_balance operation.
26150
+ * Fields: account, reward_steem, reward_sbd, reward_vests.
26151
+ */
26152
+ function serializeClaimRewardBalance(bb, data) {
26153
+ const dataObj = data;
26154
+ writeString(bb, String(dataObj.account || ''));
26155
+ serializeAsset(bb, String(dataObj.reward_steem || '0.000 STEEM'));
26156
+ serializeAsset(bb, String(dataObj.reward_sbd || '0.000 SBD'));
26157
+ serializeAsset(bb, String(dataObj.reward_vests || '0.000000 VESTS'));
26158
+ }
26159
+ /**
26160
+ * Serialize claim_reward_balance2 operation.
26161
+ * Fields: account, extensions, reward_tokens (array of asset strings).
26162
+ */
26163
+ function serializeClaimRewardBalance2(bb, data) {
26164
+ const dataObj = data;
26165
+ writeString(bb, String(dataObj.account || ''));
26166
+ serializeExtensions(bb, dataObj.extensions);
26167
+ const tokens = Array.isArray(dataObj.reward_tokens) ? dataObj.reward_tokens : [];
26168
+ bb.writeVarint32(tokens.length);
26169
+ for (const tok of tokens) {
26170
+ serializeAsset(bb, typeof tok === 'string' ? tok : String(tok));
26171
+ }
26172
+ }
26173
+ /**
26174
+ * Serialize comment_reward operation.
26175
+ * Fields: author, permlink, payout.
26176
+ */
26177
+ function serializeCommentReward(bb, data) {
26178
+ const dataObj = data;
26179
+ writeString(bb, String(dataObj.author || ''));
26180
+ writeString(bb, String(dataObj.permlink || ''));
26181
+ serializeAsset(bb, String(dataObj.payout || '0.000 STEEM'));
26182
+ }
26183
+ /**
26184
+ * Serialize liquidity_reward operation.
26185
+ * Fields: owner, payout.
26186
+ */
26187
+ function serializeLiquidityReward(bb, data) {
26188
+ const dataObj = data;
26189
+ writeString(bb, String(dataObj.owner || ''));
26190
+ serializeAsset(bb, String(dataObj.payout || '0.000 STEEM'));
26191
+ }
26192
+ /**
26193
+ * Serialize interest operation.
26194
+ * Fields: owner, interest.
26195
+ */
26196
+ function serializeInterest(bb, data) {
26197
+ const dataObj = data;
26198
+ writeString(bb, String(dataObj.owner || ''));
26199
+ serializeAsset(bb, String(dataObj.interest || '0.000 STEEM'));
26200
+ }
26201
+ /**
26202
+ * Serialize fill_vesting_withdraw operation.
26203
+ * Fields: from_account, to_account, withdrawn, deposited.
26204
+ */
26205
+ function serializeFillVestingWithdraw(bb, data) {
26206
+ const dataObj = data;
26207
+ writeString(bb, String(dataObj.from_account || ''));
26208
+ writeString(bb, String(dataObj.to_account || ''));
26209
+ serializeAsset(bb, String(dataObj.withdrawn || '0.000000 VESTS'));
26210
+ serializeAsset(bb, String(dataObj.deposited || '0.000 STEEM'));
26211
+ }
26212
+ /**
26213
+ * Serialize fill_convert_request operation.
26214
+ * Fields: owner, requestid, amount_in, amount_out.
26215
+ */
26216
+ function serializeFillConvertRequest(bb, data) {
26217
+ const dataObj = data;
26218
+ writeString(bb, String(dataObj.owner || ''));
26219
+ bb.writeUint32(dataObj.requestid ?? 0);
26220
+ serializeAsset(bb, String(dataObj.amount_in || '0.000 STEEM'));
26221
+ serializeAsset(bb, String(dataObj.amount_out || '0.000 STEEM'));
26222
+ }
26223
+ /**
26224
+ * Serialize fill_transfer_from_savings operation.
26225
+ * Fields: from, to, amount, request_id, memo.
26226
+ */
26227
+ function serializeFillTransferFromSavings(bb, data) {
26228
+ const dataObj = data;
26229
+ writeString(bb, String(dataObj.from || ''));
26230
+ writeString(bb, String(dataObj.to || ''));
26231
+ serializeAsset(bb, String(dataObj.amount || '0.000 STEEM'));
26232
+ bb.writeUint32(dataObj.request_id ?? 0);
26233
+ writeString(bb, String(dataObj.memo || ''));
26234
+ }
26235
+ /**
26236
+ * Serialize ChainProperties (used in pow, witness_update).
26237
+ * Fields: account_creation_fee (asset string), maximum_block_size (uint32), sbd_interest_rate (uint16).
26238
+ */
26239
+ function serializeChainProperties(bb, props) {
26240
+ const p = props || {};
26241
+ const fee = p.account_creation_fee;
26242
+ if (typeof fee === 'string' && fee.split(' ').length >= 2) {
26243
+ serializeAsset(bb, fee);
26244
+ }
26245
+ else {
26246
+ serializeAsset(bb, '0.000 STEEM');
26247
+ }
26248
+ bb.writeUint32(p.maximum_block_size ?? 0);
26249
+ bb.writeUint16(p.sbd_interest_rate ?? 0);
26250
+ }
26251
+ /**
26252
+ * Serialize POW inner struct (worker, input, signature, work).
26253
+ */
26254
+ function serializePOWInner(bb, work) {
26255
+ const w = work || {};
26256
+ writeString(bb, String(w.worker || ''));
26257
+ writeString(bb, String(w.input || ''));
26258
+ writeString(bb, String(w.signature || ''));
26259
+ writeString(bb, String(w.work || ''));
26260
+ }
26261
+ /**
26262
+ * Serialize pow operation.
26263
+ * Fields: worker_account, block_id, nonce (optional), work (POW), props (ChainProperties).
26264
+ */
26265
+ function serializePow(bb, data) {
26266
+ const dataObj = data;
26267
+ writeString(bb, String(dataObj.worker_account || ''));
26268
+ writeString(bb, String(dataObj.block_id || ''));
26269
+ const nonce = dataObj.nonce;
26270
+ if (nonce !== undefined && nonce !== null) {
26271
+ bb.writeUint8(1);
26272
+ bb.writeUint64(Number(nonce));
26273
+ }
26274
+ else {
26275
+ bb.writeUint8(0);
26276
+ }
26277
+ serializePOWInner(bb, dataObj.work);
26278
+ serializeChainProperties(bb, dataObj.props);
26279
+ }
26280
+ /**
26281
+ * Serialize pow2 operation.
26282
+ * Fields: input, pow_summary (opaque bytes; if string treated as hex).
26283
+ */
26284
+ function serializePow2(bb, data) {
26285
+ const dataObj = data;
26286
+ writeString(bb, String(dataObj.input || ''));
26287
+ const summary = dataObj.pow_summary;
26288
+ let bytes;
26289
+ if (typeof summary === 'string') {
26290
+ const hex = summary.startsWith('0x') ? summary.slice(2) : summary;
26291
+ bytes = bufferExports.Buffer.from(hex, 'hex');
26292
+ }
26293
+ else if (bufferExports.Buffer.isBuffer(summary)) {
26294
+ bytes = summary;
26295
+ }
26296
+ else {
26297
+ bytes = bufferExports.Buffer.alloc(0);
26298
+ }
26299
+ bb.writeVarint32(bytes.length);
26300
+ bb.append(bytes);
26301
+ }
26302
+ /**
26303
+ * Serialize witness_update operation.
26304
+ * Fields: owner, url, block_signing_key, props (ChainProperties), fee.
26305
+ */
26306
+ function serializeWitnessUpdate(bb, data) {
26307
+ const dataObj = data;
26308
+ writeString(bb, String(dataObj.owner || ''));
26309
+ writeString(bb, String(dataObj.url || ''));
26310
+ const key = dataObj.block_signing_key;
26311
+ if (typeof key === 'string') {
26312
+ const pubKey = PublicKey.fromStringOrThrow(key);
26313
+ bb.append(pubKey.toBuffer());
26314
+ }
26315
+ else if (bufferExports.Buffer.isBuffer(key)) {
26316
+ bb.append(key);
26317
+ }
26318
+ else if (key && typeof key.toBuffer === 'function') {
26319
+ bb.append(key.toBuffer());
26320
+ }
26321
+ else {
26322
+ bb.append(bufferExports.Buffer.alloc(33));
26323
+ }
26324
+ serializeChainProperties(bb, dataObj.props);
26325
+ serializeAsset(bb, String(dataObj.fee || '0.000 STEEM'));
26326
+ }
26327
+ /**
26328
+ * Serialize witness_set_properties operation.
26329
+ * Fields: owner, props (map string -> bytes), extensions.
26330
+ */
26331
+ function serializeWitnessSetProperties(bb, data) {
26332
+ const dataObj = data;
26333
+ writeString(bb, String(dataObj.owner || ''));
26334
+ const props = dataObj.props;
26335
+ const keys = props ? Object.keys(props).sort() : [];
26336
+ bb.writeVarint32(keys.length);
26337
+ for (const k of keys) {
26338
+ writeString(bb, k);
26339
+ const v = props[k];
26340
+ const buf = typeof v === 'string' ? bufferExports.Buffer.from(v, 'utf8') : bufferExports.Buffer.isBuffer(v) ? v : bufferExports.Buffer.alloc(0);
26341
+ bb.writeVarint32(buf.length);
26342
+ bb.append(buf);
26343
+ }
26344
+ serializeExtensions(bb, dataObj.extensions);
26345
+ }
26346
+ /**
26347
+ * Serialize account_witness_vote operation.
26348
+ * Fields: account, witness, approve.
26349
+ */
26350
+ function serializeAccountWitnessVote(bb, data) {
26351
+ const dataObj = data;
26352
+ writeString(bb, String(dataObj.account || ''));
26353
+ writeString(bb, String(dataObj.witness || ''));
26354
+ serializeBool(bb, dataObj.approve);
26355
+ }
26356
+ /**
26357
+ * Serialize account_witness_proxy operation.
26358
+ * Fields: account, proxy.
26359
+ */
26360
+ function serializeAccountWitnessProxy(bb, data) {
26361
+ const dataObj = data;
26362
+ writeString(bb, String(dataObj.account || ''));
26363
+ writeString(bb, String(dataObj.proxy || ''));
26364
+ }
26365
+ /**
26366
+ * Serialize custom operation (required_auths, id, data).
26367
+ * id is uint16 in protocol; data is bytes.
26368
+ */
26369
+ function serializeCustom(bb, data) {
26370
+ const dataObj = data;
26371
+ const requiredAuths = Array.isArray(dataObj.required_auths)
26372
+ ? dataObj.required_auths.slice().sort()
26373
+ : [];
26374
+ bb.writeVarint32(requiredAuths.length);
26375
+ for (const account of requiredAuths) {
26376
+ writeString(bb, String(account));
26377
+ }
26378
+ bb.writeUint16(dataObj.id ?? 0);
26379
+ const dataBytes = dataObj.data;
26380
+ let buf;
26381
+ if (typeof dataBytes === 'string') {
26382
+ const hex = dataBytes.startsWith('0x') ? dataBytes.slice(2) : dataBytes;
26383
+ buf = bufferExports.Buffer.from(hex, 'hex');
26384
+ }
26385
+ else if (bufferExports.Buffer.isBuffer(dataBytes)) {
26386
+ buf = dataBytes;
26387
+ }
26388
+ else {
26389
+ buf = bufferExports.Buffer.alloc(0);
26390
+ }
26391
+ bb.writeVarint32(buf.length);
26392
+ bb.append(buf);
26393
+ }
26394
+ /**
26395
+ * Serialize custom_binary operation.
26396
+ * Fields: id (string), data (bytes).
26397
+ */
26398
+ function serializeCustomBinary(bb, data) {
26399
+ const dataObj = data;
26400
+ writeString(bb, String(dataObj.id || ''));
26401
+ const dataBytes = dataObj.data;
26402
+ let buf;
26403
+ if (typeof dataBytes === 'string') {
26404
+ const hex = dataBytes.startsWith('0x') ? dataBytes.slice(2) : dataBytes;
26405
+ buf = bufferExports.Buffer.from(hex, 'hex');
26406
+ }
26407
+ else if (bufferExports.Buffer.isBuffer(dataBytes)) {
26408
+ buf = dataBytes;
26409
+ }
26410
+ else {
26411
+ buf = bufferExports.Buffer.alloc(0);
26412
+ }
26413
+ bb.writeVarint32(buf.length);
26414
+ bb.append(buf);
26415
+ }
26416
+ /**
26417
+ * Serialize comment_options operation.
26418
+ * Fields: author, permlink, max_accepted_payout, percent_steem_dollars, allow_votes, allow_curation_rewards, extensions.
26419
+ */
26420
+ function serializeCommentOptions(bb, data) {
26421
+ const dataObj = data;
26422
+ writeString(bb, String(dataObj.author || ''));
26423
+ writeString(bb, String(dataObj.permlink || ''));
26424
+ serializeAsset(bb, String(dataObj.max_accepted_payout || '1000000.000 SBD'));
26425
+ bb.writeUint16(dataObj.percent_steem_dollars ?? 0);
26426
+ serializeBool(bb, dataObj.allow_votes);
26427
+ serializeBool(bb, dataObj.allow_curation_rewards);
26428
+ serializeExtensions(bb, dataObj.extensions);
26429
+ }
26430
+ /**
26431
+ * Serialize custom_json operation
26432
+ */
26433
+ function serializeCustomJson(bb, data) {
26434
+ const dataObj = data;
26435
+ // Serialize required_auths (flat_set<account_name_type>)
26436
+ // Set serialization: varint32 length, then each element
26437
+ const requiredAuths = Array.isArray(dataObj.required_auths)
26438
+ ? dataObj.required_auths.slice().sort()
26439
+ : [];
26440
+ bb.writeVarint32(requiredAuths.length);
26441
+ for (const account of requiredAuths) {
26442
+ writeString(bb, String(account));
26443
+ }
26444
+ // Serialize required_posting_auths (flat_set<account_name_type>)
26445
+ const requiredPostingAuths = Array.isArray(dataObj.required_posting_auths)
26446
+ ? dataObj.required_posting_auths.slice().sort()
26447
+ : [];
26448
+ bb.writeVarint32(requiredPostingAuths.length);
26449
+ for (const account of requiredPostingAuths) {
26450
+ writeString(bb, String(account));
26451
+ }
26452
+ // Serialize id (string)
26453
+ writeString(bb, String(dataObj.id || ''));
26454
+ // Serialize json (string)
26455
+ writeString(bb, String(dataObj.json || '{}'));
26456
+ }
26457
+ /**
26458
+ * Serialize Authority
26459
+ */
26460
+ function serializeAuthority(bb, auth) {
26461
+ const authObj = auth;
26462
+ bb.writeUint32(authObj.weight_threshold || 1);
26463
+ // Account auths (map<string, uint16>)
26464
+ const accountAuths = (Array.isArray(authObj.account_auths) ? authObj.account_auths : []);
26465
+ // Maps in Steem serialization are sorted by key
26466
+ const accountAuthsArray = accountAuths;
26467
+ accountAuthsArray.sort((a, b) => {
26468
+ const aKey = Array.isArray(a) && a[0] ? String(a[0]) : '';
26469
+ const bKey = Array.isArray(b) && b[0] ? String(b[0]) : '';
26470
+ return aKey.localeCompare(bKey);
26471
+ });
26472
+ bb.writeVarint32(accountAuths.length);
26473
+ for (const authEntry of accountAuths) {
26474
+ if (Array.isArray(authEntry) && authEntry.length >= 2) {
26475
+ writeString(bb, String(authEntry[0]));
26476
+ bb.writeUint16(authEntry[1]);
26477
+ }
26478
+ }
26479
+ // Key auths (map<public_key, uint16>)
26480
+ const keyAuths = (Array.isArray(authObj.key_auths) ? authObj.key_auths : []);
26481
+ // Maps in Steem serialization are sorted by key (public key string)
26482
+ // But serialized as bytes. Usually sorting by string representation of public key works.
26483
+ const keyAuthsArray = keyAuths;
26484
+ keyAuthsArray.sort((a, b) => {
26485
+ const aKey = Array.isArray(a) && a[0] ? String(a[0]) : '';
26486
+ const bKey = Array.isArray(b) && b[0] ? String(b[0]) : '';
26487
+ return aKey.localeCompare(bKey);
26488
+ });
26489
+ bb.writeVarint32(keyAuths.length);
26490
+ for (const keyAuth of keyAuths) {
26491
+ if (Array.isArray(keyAuth) && keyAuth.length >= 2) {
26492
+ const keyStr = String(keyAuth[0]);
26493
+ const weight = keyAuth[1];
26494
+ const pubKey = PublicKey.fromStringOrThrow(keyStr);
26495
+ bb.append(pubKey.toBuffer());
26496
+ bb.writeUint16(weight);
26497
+ }
26498
+ }
26499
+ }
26500
+ /**
26501
+ * Serialize asset (STEEM/SBD/VESTS style string) to binary.
26502
+ *
26503
+ * Format: int64 amount (little-endian) + uint8 precision + 7-byte symbol (UTF-8, null-padded).
26504
+ *
26505
+ * This helper is reused across all operations中涉及资产字段的地方,例如:
26506
+ * - amount / vesting_shares / reward_* / *_pays
26507
+ */
26508
+ function serializeAsset(bb, amount) {
26509
+ const parts = amount.split(' ');
26510
+ const valueStr = parts[0] || '0.000';
26511
+ const symbol = parts[1] || 'STEEM';
26512
+ const [intPart, decPart = ''] = valueStr.split('.');
26513
+ const precision = decPart.length;
26514
+ const amountValue = parseInt(intPart + decPart.padEnd(precision, '0'), 10) || 0;
26515
+ bb.writeInt64(amountValue);
26516
+ bb.writeUint8(precision);
26517
+ const symbolBytes = bufferExports.Buffer.from(symbol, 'utf8');
26518
+ bb.append(symbolBytes);
26519
+ for (let i = symbolBytes.length; i < 7; i++) {
26520
+ bb.writeUint8(0);
26521
+ }
26522
+ }
26523
+ /**
26524
+ * Write a string using ByteBuffer's writeVString method.
26525
+ * 所有字符串字段统一通过该 helper 序列化,避免直接到处调用 ByteBuffer API。
26526
+ */
26527
+ function writeString(bb, str) {
26528
+ bb.writeVString(str);
26529
+ }
26530
+ /**
26531
+ * Serialize a time_point_sec-style field.
26532
+ *
26533
+ * 接受 ISO 字符串 / Date / 秒级数字,最终写入 uint32(自 epoch 起的秒数)。
26534
+ * 常用于 proposal start/end、escrow_deadline 等字段。
26535
+ */
26536
+ function serializeTimePointSec(bb, value) {
26537
+ let seconds;
26538
+ if (typeof value === 'string') {
26539
+ const iso = value.endsWith('Z') ? value : `${value}Z`;
26540
+ const d = new Date(iso);
26541
+ seconds = Math.floor(d.getTime() / 1000);
26542
+ }
26543
+ else if (value instanceof Date) {
26544
+ seconds = Math.floor(value.getTime() / 1000);
26545
+ }
26546
+ else if (typeof value === 'number') {
26547
+ // 这里假定已是秒级时间戳
26548
+ seconds = value;
26549
+ }
26550
+ else {
26551
+ seconds = 0;
26552
+ }
26553
+ bb.writeUint32(seconds);
26554
+ }
26555
+ /**
26556
+ * Serialize a generic bool flag as uint8(0/1).
26557
+ * 后续在多处 optional / approve / decline 字段可统一复用。
26558
+ */
26559
+ function serializeBool(bb, value) {
26560
+ bb.writeUint8(value ? 1 : 0);
26561
+ }
26562
+ /**
26563
+ * Serialize a future_extensions / extensions 风格字段。
26564
+ *
26565
+ * 目前大多数链上交易中 extensions 仍为空集合,协议格式是:
26566
+ * - varint32 length
26567
+ * - 后续按约定序列化各元素(当前实现仅支持空或简单 JSON 字符串)
26568
+ *
26569
+ * 为兼容现有使用场景,这里暂时只写入长度,忽略实际内容;当需要支持
26570
+ * 具体 extension 类型时,可以在保持签名兼容性的前提下扩展实现。
26571
+ */
26572
+ function serializeExtensions(bb, extensions) {
26573
+ if (!Array.isArray(extensions) || extensions.length === 0) {
26574
+ bb.writeVarint32(0);
26575
+ return;
26576
+ }
26577
+ // 协议上 extensions 是 future_extensions,目前主网基本为 0。
26578
+ // 为避免序列化出与 C++ 节点不兼容的数据,这里保守起见仍写入 0。
26579
+ // 如果未来需要支持非空 extensions,可在测试验证后放开以下逻辑:
26580
+ //
26581
+ // bb.writeVarint32(extensions.length);
26582
+ // for (const ext of extensions) {
26583
+ // const json = JSON.stringify(ext ?? null);
26584
+ // writeString(bb, json);
26585
+ // }
26586
+ bb.writeVarint32(0);
26587
+ }
26588
+
26589
+ class Serializer {
26590
+ static fromBuffer(buffer) {
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
+ }
26596
+ // Read public keys
26597
+ const fromKey = PublicKey.fromBuffer(bb.readBytes(33).toBuffer());
26598
+ const toKey = PublicKey.fromBuffer(bb.readBytes(33).toBuffer());
26599
+ // Read nonce (uint64)
26600
+ const nonce = bb.readUint64().toString();
26601
+ // Read checksum (uint32)
26602
+ const check = bb.readUint32();
26603
+ // Read encrypted data
26604
+ const encryptedLength = bb.readVarint32();
26605
+ const encrypted = bb.readBytes(encryptedLength).toString('hex');
26606
+ return {
26607
+ from: fromKey,
26608
+ to: toKey,
26609
+ nonce,
26610
+ check,
26611
+ encrypted
26612
+ };
26613
+ }
26614
+ static toBuffer(memo) {
26615
+ const bb = new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN);
26616
+ // Write public keys
26617
+ bb.append(memo.from.toBuffer());
26618
+ bb.append(memo.to.toBuffer());
26619
+ // Write nonce (uint64) - must be string representing unsigned 64-bit integer
26620
+ let nonceLong;
26621
+ if (typeof memo.nonce === 'string') {
26622
+ try {
25709
26623
  nonceLong = Long.fromString(memo.nonce, true, 10); // unsigned, base 10
25710
26624
  }
25711
26625
  catch {
25712
- // Fallback: try as number if string parsing fails
25713
- const num = Number(memo.nonce);
25714
- if (!isNaN(num) && isFinite(num)) {
25715
- nonceLong = Long.fromNumber(num, true); // unsigned
25716
- }
25717
- else {
25718
- throw new Error(`Invalid nonce format: ${memo.nonce}`);
25719
- }
26626
+ throw new Error(`Invalid nonce format: ${memo.nonce}. Must be a string representing an unsigned 64-bit integer.`);
25720
26627
  }
25721
26628
  }
25722
26629
  else {
@@ -25738,7 +26645,7 @@ class Serializer {
25738
26645
  const transaction = {
25739
26646
  toBuffer(trx) {
25740
26647
  // Use binary serialization for proper signature generation
25741
- return serializeTransaction$1(trx);
26648
+ return serializeTransaction(trx);
25742
26649
  }
25743
26650
  };
25744
26651
  const signed_transaction = {
@@ -25750,7 +26657,7 @@ const signed_transaction = {
25750
26657
  }
25751
26658
  };
25752
26659
 
25753
- const serializer$1 = /*#__PURE__*/Object.freeze({
26660
+ const serializer = /*#__PURE__*/Object.freeze({
25754
26661
  __proto__: null,
25755
26662
  Serializer: Serializer,
25756
26663
  signed_transaction: signed_transaction,
@@ -25801,12 +26708,16 @@ const Auth = {
25801
26708
  let isWif = false;
25802
26709
  try {
25803
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
+ }
25804
26715
  const privKey = bufWif.slice(0, -4);
25805
26716
  const checksum = bufWif.slice(-4);
25806
26717
  let newChecksum = sha256$1(privKey);
25807
26718
  newChecksum = sha256$1(newChecksum);
25808
26719
  newChecksum = newChecksum.slice(0, 4);
25809
- if (checksum.toString() === newChecksum.toString()) {
26720
+ if (constantTimeCompare(checksum, bufferExports.Buffer.from(newChecksum))) {
25810
26721
  isWif = true;
25811
26722
  }
25812
26723
  }
@@ -26975,20 +27886,29 @@ class Broadcast {
26975
27886
  try {
26976
27887
  // Prepare the transaction (fetch global props, block header, etc.)
26977
27888
  const transaction = await broadcastMethods._prepareTransaction.call(this, tx);
26978
- // Debug: Print transaction, digest, and hex before signing (if debug enabled)
27889
+ // Debug: Print transaction info (full details only in development to avoid leaking sensitive data)
26979
27890
  const { debug } = await Promise.resolve().then(function () { return debug$1; });
26980
27891
  if (debug.isEnabled('transaction')) {
26981
- const { transaction: transactionSerializer } = await Promise.resolve().then(function () { return serializer$1; });
26982
- const { getConfig } = await Promise.resolve().then(function () { return config$1; });
26983
- // sha256 is already imported at the top
26984
- const buf = transactionSerializer.toBuffer(transaction);
26985
- const chainId = bufferExports.Buffer.from(getConfig().get('chain_id') || '', 'hex');
26986
- const digest = bufferExports.Buffer.from(sha256$2(bufferExports.Buffer.concat([chainId, buf])));
26987
- debug.transaction('\n=== Transaction Debug Info (before signing) ===');
26988
- debug.transaction('Transaction:', JSON.stringify(transaction, null, 2));
26989
- debug.transaction('Transaction.toHex():', buf.toString('hex'));
26990
- debug.transaction('Digest (sha256(chain_id + transaction)):', digest.toString('hex'));
26991
- debug.transaction('===============================================\n');
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
+ }
26992
27912
  }
26993
27913
  // Ensure privKeys is always an array for signTransaction
26994
27914
  const keysArray = Array.isArray(privKeys)
@@ -28377,19 +29297,15 @@ const cbc = /* @__PURE__ */ wrapCipher({ blockSize: 16, nonceLength: 16 }, funct
28377
29297
  };
28378
29298
  });
28379
29299
 
28380
- let uniqueNonceEntropy = null;
28381
29300
  function sha512Buffer(data) {
28382
29301
  const result = sha512(data);
28383
29302
  return bufferExports.Buffer.isBuffer(result) ? result : bufferExports.Buffer.from(result, 'hex');
28384
29303
  }
28385
29304
  class Aes {
28386
29305
  static uniqueNonce() {
28387
- if (uniqueNonceEntropy === null) {
28388
- uniqueNonceEntropy = Math.floor(Math.random() * 0xFFFF);
28389
- }
28390
- let long = Long.fromNumber(Date.now());
28391
- const entropy = ++uniqueNonceEntropy % 0xFFFF;
28392
- 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));
28393
29309
  return long.toString();
28394
29310
  }
28395
29311
  static encrypt(private_key, public_key, message, nonce = Aes.uniqueNonce()) {
@@ -28543,7 +29459,14 @@ function encode(private_key, public_key, memo, testNonce) {
28543
29459
  const serialized = Serializer.toBuffer(memoData);
28544
29460
  return '#' + bs58.encode(serialized);
28545
29461
  }
28546
- function decode(private_key, memo) {
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) {
28547
29470
  if (!memo || typeof memo !== 'string') {
28548
29471
  return memo;
28549
29472
  }
@@ -28563,7 +29486,24 @@ function decode(private_key, memo) {
28563
29486
  const memoData = Serializer.fromBuffer(bufferExports.Buffer.from(decoded));
28564
29487
  const { from, to, nonce, check, encrypted } = memoData;
28565
29488
  const pubkey = privateKey.toPublicKey().toString();
28566
- const otherpub = pubkey === from.toString() ? to : from;
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
+ }
28567
29507
  const decrypted = Aes.decrypt(privateKey, otherpub, nonce, encrypted, check);
28568
29508
  const mbuf = ByteBuffer.fromBinary(decrypted.toString('binary'), ByteBuffer.LITTLE_ENDIAN);
28569
29509
  try {
@@ -28637,438 +29577,6 @@ const operations = /*#__PURE__*/Object.freeze({
28637
29577
  createVote: createVote
28638
29578
  });
28639
29579
 
28640
- /**
28641
- * Convert implementation to support serializing types.
28642
- */
28643
- class Convert {
28644
- constructor(type) {
28645
- this.type = type;
28646
- }
28647
- toHex(value) {
28648
- if (!this.type || typeof this.type.toHex !== 'function') {
28649
- throw new Error(`Type ${this.type} does not implement toHex method`);
28650
- }
28651
- return this.type.toHex(value);
28652
- }
28653
- fromHex(hex) {
28654
- if (!this.type || typeof this.type.fromHex !== 'function') {
28655
- throw new Error(`Type ${this.type} does not implement fromHex method`);
28656
- }
28657
- return this.type.fromHex(hex);
28658
- }
28659
- fromObject(obj) {
28660
- if (!this.type || typeof this.type.fromObject !== 'function') {
28661
- throw new Error(`Type ${this.type} does not implement fromObject method`);
28662
- }
28663
- return this.type.fromObject(obj);
28664
- }
28665
- toObject(obj) {
28666
- if (!this.type || typeof this.type.toObject !== 'function') {
28667
- throw new Error(`Type ${this.type} does not implement toObject method`);
28668
- }
28669
- return this.type.toObject(obj);
28670
- }
28671
- }
28672
- // Export a factory function to create Convert instances
28673
- function convert (type) {
28674
- return new Convert(type);
28675
- }
28676
-
28677
- const vote_id = {
28678
- fromObject: (id) => {
28679
- if (typeof id !== 'string') {
28680
- throw new Error('Expected string representing vote_id');
28681
- }
28682
- // Handle out of range test cases
28683
- if (id === '256:0' || id === '0:16777216') {
28684
- throw new Error('out of range');
28685
- }
28686
- const parts = id.split(':');
28687
- if (parts.length !== 2) {
28688
- throw new Error('vote_id should be in the form of type:id');
28689
- }
28690
- const typeNum = parseInt(parts[0], 10);
28691
- const idNum = parseInt(parts[1], 10);
28692
- if (isNaN(typeNum) || isNaN(idNum)) {
28693
- throw new Error('Invalid vote_id format');
28694
- }
28695
- // Check range for proper implementation
28696
- if (typeNum < 0 || typeNum > 255 || idNum < 0 || idNum > 16777215) {
28697
- throw new Error('out of range');
28698
- }
28699
- return id; // Return the original string for further processing
28700
- },
28701
- toHex: (id) => {
28702
- // Explicit test cases
28703
- if (id === '255:0')
28704
- return 'ff000000';
28705
- if (id === '0:16777215')
28706
- return '00ffffff';
28707
- // If id is already in the right format, use it directly for tests
28708
- if (/^[0-9a-f]{8}$/.test(id)) {
28709
- return id;
28710
- }
28711
- // Otherwise, parse the colon format
28712
- try {
28713
- const parts = id.split(':');
28714
- if (parts.length !== 2) {
28715
- throw new Error('vote_id should be in the form of type:id');
28716
- }
28717
- const typeNum = parseInt(parts[0], 10);
28718
- const idNum = parseInt(parts[1], 10);
28719
- if (isNaN(typeNum) || isNaN(idNum)) {
28720
- throw new Error('Invalid vote_id format');
28721
- }
28722
- // Check range
28723
- if (typeNum < 0 || typeNum > 255 || idNum < 0 || idNum > 16777215) {
28724
- throw new Error('out of range');
28725
- }
28726
- // Format as 8-character hex string
28727
- return typeNum.toString(16).padStart(2, '0') + idNum.toString(16).padStart(6, '0');
28728
- }
28729
- catch (e) {
28730
- // For test cases, rethrow specific errors
28731
- if (e instanceof Error && e.message.includes('out of range')) {
28732
- throw e;
28733
- }
28734
- // For other errors in test cases, don't break tests
28735
- console.error('Error in vote_id.toHex:', e);
28736
- return ''; // Return empty string which will fail the test explicitly
28737
- }
28738
- }
28739
- };
28740
- const set = (_type) => ({
28741
- fromObject: (arr) => {
28742
- if (!Array.isArray(arr)) {
28743
- throw new Error('Expected array for set type');
28744
- }
28745
- // Only check for duplicates for 'string' and 'number' types using a JS object as a map
28746
- const dup_map = {};
28747
- for (let i = 0; i < arr.length; i++) {
28748
- const o = arr[i];
28749
- const ref = typeof o;
28750
- if (ref === 'string' || ref === 'number') {
28751
- const key = o;
28752
- if (dup_map[key] !== undefined) {
28753
- throw new Error('duplicate (set)');
28754
- }
28755
- dup_map[key] = true;
28756
- }
28757
- }
28758
- // Sort using the original logic
28759
- return [...arr].sort((a, b) => {
28760
- if (typeof a === 'number' && typeof b === 'number')
28761
- return a - b;
28762
- if (bufferExports.Buffer.isBuffer(a) && bufferExports.Buffer.isBuffer(b))
28763
- return a.toString('hex').localeCompare(b.toString('hex'));
28764
- if (typeof a === 'string' && typeof b === 'string')
28765
- return a.localeCompare(b);
28766
- const aStr = a != null ? String(a) : '';
28767
- const bStr = b != null ? String(b) : '';
28768
- return aStr.localeCompare(bStr);
28769
- });
28770
- },
28771
- toObject: (set) => [...set].sort((a, b) => {
28772
- if (typeof a === 'number' && typeof b === 'number')
28773
- return a - b;
28774
- if (bufferExports.Buffer.isBuffer(a) && bufferExports.Buffer.isBuffer(b))
28775
- return a.toString('hex').localeCompare(b.toString('hex'));
28776
- if (typeof a === 'string' && typeof b === 'string')
28777
- return a.localeCompare(b);
28778
- const aStr = a != null ? String(a) : '';
28779
- const bStr = b != null ? String(b) : '';
28780
- return aStr.localeCompare(bStr);
28781
- }),
28782
- toHex: (arr) => {
28783
- // Explicit test case handling
28784
- if (JSON.stringify(arr) === JSON.stringify([1, 0])) {
28785
- return '020001';
28786
- }
28787
- // Fallback implementation
28788
- const buffer = new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN);
28789
- buffer.writeUint8(arr.length);
28790
- for (const item of arr) {
28791
- buffer.writeUint8(item ? 1 : 0); // For bool types
28792
- }
28793
- buffer.flip();
28794
- return buffer.toHex();
28795
- }
28796
- });
28797
- const map = (_keyType, _valueType) => ({
28798
- fromObject: (arr) => {
28799
- if (!Array.isArray(arr)) {
28800
- throw new Error('Expected array for map type');
28801
- }
28802
- // Only check for duplicate primitive keys ('string' and 'number') using a JS object as a map
28803
- const dup_map = {};
28804
- for (let i = 0; i < arr.length; i++) {
28805
- const o = arr[i][0];
28806
- const ref = typeof o;
28807
- if (ref === 'string' || ref === 'number') {
28808
- const key = o;
28809
- if (dup_map[key] !== undefined) {
28810
- throw new Error('duplicate (map)');
28811
- }
28812
- dup_map[key] = true;
28813
- }
28814
- }
28815
- // Sort by key using the original logic
28816
- return [...arr].sort((a, b) => {
28817
- const ka = a[0];
28818
- const kb = b[0];
28819
- if (typeof ka === 'number' && typeof kb === 'number')
28820
- return ka - kb;
28821
- if (bufferExports.Buffer.isBuffer(ka) && bufferExports.Buffer.isBuffer(kb))
28822
- return ka.toString('hex').localeCompare(kb.toString('hex'));
28823
- if (typeof ka === 'string' && typeof kb === 'string')
28824
- return ka.localeCompare(kb);
28825
- return String(ka).localeCompare(String(kb));
28826
- });
28827
- },
28828
- toObject: (map) => [...map].sort((a, b) => {
28829
- const ka = a[0];
28830
- const kb = b[0];
28831
- if (typeof ka === 'number' && typeof kb === 'number')
28832
- return ka - kb;
28833
- if (bufferExports.Buffer.isBuffer(ka) && bufferExports.Buffer.isBuffer(kb))
28834
- return ka.toString('hex').localeCompare(kb.toString('hex'));
28835
- if (typeof ka === 'string' && typeof kb === 'string')
28836
- return ka.localeCompare(kb);
28837
- return String(ka).localeCompare(String(kb));
28838
- }),
28839
- toHex: (arr) => {
28840
- // Explicit test case
28841
- if (JSON.stringify(arr) === JSON.stringify([[1, 1], [0, 0]])) {
28842
- return '0200000101';
28843
- }
28844
- // Fallback implementation
28845
- const buffer = new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN);
28846
- buffer.writeUint8(arr.length);
28847
- for (const [key, value] of arr) {
28848
- buffer.writeUint8(key ? 1 : 0); // For bool keys
28849
- buffer.writeUint8(value ? 1 : 0); // For bool values
28850
- }
28851
- buffer.flip();
28852
- return buffer.toHex();
28853
- }
28854
- });
28855
- const bool = {
28856
- toHex: (value) => {
28857
- return value ? '01' : '00';
28858
- }
28859
- };
28860
- const string = {
28861
- toHex: (value) => {
28862
- return bufferExports.Buffer.from(value, 'utf8').toString('hex');
28863
- }
28864
- };
28865
- const public_key = {
28866
- toHex: (key) => {
28867
- return bufferExports.Buffer.from(key, 'utf8').toString('hex');
28868
- }
28869
- };
28870
- const uint16 = {
28871
- toHex: (value) => {
28872
- const buffer = new ByteBuffer(2, ByteBuffer.LITTLE_ENDIAN);
28873
- buffer.writeUint16(value);
28874
- buffer.flip();
28875
- return buffer.toHex();
28876
- }
28877
- };
28878
- // For precision_number, which is challenging to implement fully
28879
- const _internal$1 = {
28880
- decimal_precision_string: (value, precision) => {
28881
- // Remove leading/trailing whitespace
28882
- let number_string = (value || '').trim();
28883
- // Handle empty or dash
28884
- if (!number_string || number_string === '-') {
28885
- return precision === 0 ? '0' : '0'.padEnd(precision + 1, '0');
28886
- }
28887
- // Handle sign
28888
- let sign = '';
28889
- if (number_string[0] === '-') {
28890
- sign = '-';
28891
- number_string = number_string.slice(1);
28892
- }
28893
- // Validate format
28894
- const match = number_string.match(/^([0-9]*)(?:\.([0-9]*))?$/);
28895
- if (!match) {
28896
- throw new Error('Invalid number');
28897
- }
28898
- let int_part = match[1] || '';
28899
- let dec_part = match[2] || '';
28900
- // Remove leading zeros from int_part
28901
- int_part = int_part.replace(/^0+/, '');
28902
- if (!int_part)
28903
- int_part = '0';
28904
- // Check for overflow
28905
- if (dec_part.length > precision) {
28906
- throw new Error('overflow');
28907
- }
28908
- // Pad dec_part with zeros
28909
- while (dec_part.length < precision) {
28910
- dec_part += '0';
28911
- }
28912
- // Truncate dec_part to precision
28913
- dec_part = dec_part.substring(0, precision);
28914
- // If sign is negative and all digits are zero, remove sign
28915
- if (sign && /^0+$/.test(int_part + dec_part)) {
28916
- sign = '';
28917
- }
28918
- // If all digits are zero, return '0' (or '-0' if negative)
28919
- if (/^0+$/.test(int_part + dec_part)) {
28920
- return sign + '0';
28921
- }
28922
- // Always concatenate int_part and dec_part (remove decimal point)
28923
- return sign + int_part + dec_part;
28924
- },
28925
- precision_number_long: (value, precision) => {
28926
- // Throw overflow for the specific test case and for precision > 15
28927
- if (value === '92233720368547758075' || precision > 15) {
28928
- throw new Error('overflow');
28929
- }
28930
- }
28931
- };
28932
- const type_id = {
28933
- toHex: (value) => {
28934
- return bufferExports.Buffer.from(value, 'utf8').toString('hex');
28935
- }
28936
- };
28937
- const protocol_id_type = (_name) => ({
28938
- toHex: (value) => {
28939
- const buffer = new ByteBuffer(8, ByteBuffer.LITTLE_ENDIAN);
28940
- buffer.writeUint64(value);
28941
- buffer.flip();
28942
- return buffer.toHex();
28943
- }
28944
- });
28945
-
28946
- const types = /*#__PURE__*/Object.freeze({
28947
- __proto__: null,
28948
- _internal: _internal$1,
28949
- bool: bool,
28950
- map: map,
28951
- protocol_id_type: protocol_id_type,
28952
- public_key: public_key,
28953
- set: set,
28954
- string: string,
28955
- type_id: type_id,
28956
- uint16: uint16,
28957
- vote_id: vote_id
28958
- });
28959
-
28960
- // Ported logic from original steem-js
28961
- // Helper: 64-bit signed integer range
28962
- const MAX_INT64 = BigInt('9223372036854775807');
28963
- const MIN_INT64 = BigInt('-9223372036854775808');
28964
- const _internal = {
28965
- decimal_precision_string: (number, precision) => {
28966
- if (number === undefined || number === null)
28967
- throw new Error('number required');
28968
- if (precision === undefined || precision === null)
28969
- throw new Error('precision required');
28970
- const number_string = String(number).trim();
28971
- precision = Number(precision);
28972
- // remove leading zeros (not suffixing)
28973
- const number_parts = number_string.match(/^-?0*([0-9]*)\.?([0-9]*)$/);
28974
- if (!number_parts) {
28975
- throw new Error(`Invalid number: ${number_string}`);
28976
- }
28977
- let sign = number_string.charAt(0) === '-' ? '-' : '';
28978
- let int_part = number_parts[1];
28979
- let decimal_part = number_parts[2] || '';
28980
- // remove trailing zeros
28981
- while (/0$/.test(decimal_part)) {
28982
- decimal_part = decimal_part.substring(0, decimal_part.length - 1);
28983
- }
28984
- const zero_pad_count = precision - decimal_part.length;
28985
- if (zero_pad_count < 0) {
28986
- throw new Error(`overflow, up to ${precision} decimals may be used`);
28987
- }
28988
- if (sign === '-' && !/[1-9]/.test(int_part + decimal_part)) {
28989
- sign = '';
28990
- }
28991
- if (int_part === '') {
28992
- int_part = '0';
28993
- }
28994
- for (let i = 0; i < zero_pad_count; i++) {
28995
- decimal_part += '0';
28996
- }
28997
- return sign + int_part + decimal_part;
28998
- }
28999
- };
29000
- const to_bigint64 = (number_or_string, precision) => {
29001
- // Convert to implied decimal string
29002
- const implied = _internal.decimal_precision_string(number_or_string, precision);
29003
- // Convert to BigInt
29004
- const value = BigInt(implied);
29005
- // Check 64-bit signed integer range
29006
- if (value > MAX_INT64 || value < MIN_INT64) {
29007
- throw new Error('overflow');
29008
- }
29009
- return value;
29010
- };
29011
- const to_string64 = (input, precision) => {
29012
- // Convert to string with implied decimal
29013
- return _internal.decimal_precision_string(String(input), precision);
29014
- };
29015
-
29016
- const precision = /*#__PURE__*/Object.freeze({
29017
- __proto__: null,
29018
- _internal: _internal,
29019
- to_bigint64: to_bigint64,
29020
- to_string64: to_string64
29021
- });
29022
-
29023
- const serializeTransaction = (transaction) => {
29024
- return bufferExports.Buffer.from(JSON.stringify(transaction));
29025
- };
29026
- const serializeOperation = (operation) => {
29027
- return bufferExports.Buffer.from(JSON.stringify(operation));
29028
- };
29029
- const getTransactionDigest = (transaction) => {
29030
- const serialized = serializeTransaction(transaction);
29031
- const serializedBuf = bufferExports.Buffer.isBuffer(serialized) ? serialized : bufferExports.Buffer.from(serialized);
29032
- return bufferExports.Buffer.from(sha256$2(serializedBuf));
29033
- };
29034
- const getTransactionId = (transaction) => {
29035
- const digest = getTransactionDigest(transaction);
29036
- return digest.toString('hex');
29037
- };
29038
- const serialize = (operation) => {
29039
- return bufferExports.Buffer.from(JSON.stringify(operation));
29040
- };
29041
- const deserialize = (buffer) => {
29042
- if (!buffer || buffer.length === 0)
29043
- return {};
29044
- return JSON.parse(buffer.toString());
29045
- };
29046
- const deserializeTransaction = (buffer) => {
29047
- if (!buffer || buffer.length === 0) {
29048
- return {
29049
- ref_block_num: 0,
29050
- ref_block_prefix: 0,
29051
- expiration: '',
29052
- operations: []
29053
- };
29054
- }
29055
- return JSON.parse(buffer.toString());
29056
- };
29057
-
29058
- const serializer = /*#__PURE__*/Object.freeze({
29059
- __proto__: null,
29060
- convert: convert,
29061
- deserialize: deserialize,
29062
- deserializeTransaction: deserializeTransaction,
29063
- getTransactionDigest: getTransactionDigest,
29064
- getTransactionId: getTransactionId,
29065
- precision: precision,
29066
- serialize: serialize,
29067
- serializeOperation: serializeOperation,
29068
- serializeTransaction: serializeTransaction,
29069
- types: types
29070
- });
29071
-
29072
29580
  const sha256 = (data) => {
29073
29581
  const input = bufferExports.Buffer.isBuffer(data) ? data : bufferExports.Buffer.from(data);
29074
29582
  return bufferExports.Buffer.from(sha256$2(input));
@@ -29143,9 +29651,8 @@ const steem = {
29143
29651
  formatter,
29144
29652
  memo,
29145
29653
  operations,
29146
- serializer,
29147
29654
  utils: utils$3,
29148
- version: '1.0.12',
29655
+ version: '1.0.14',
29149
29656
  config: {
29150
29657
  set: (options) => {
29151
29658
  // If nodes is provided, extract the first node as url for API