@steemit/steem-js 1.0.17 → 1.0.18

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/index.cjs CHANGED
@@ -21992,6 +21992,132 @@ if (typeof BigInt === "function") {
21992
21992
  };
21993
21993
  }
21994
21994
 
21995
+ /**
21996
+ * Chain-safe JSON normalization for account_update operations.
21997
+ * Matches steem::protocol::account_update_operation and authority (FC_REFLECT).
21998
+ * Broadcast via JSON-RPC uses fc::from_variant; malformed shapes cause bad_cast_exception.
21999
+ */
22000
+ /** Steem broadcast JSON requires json_metadata to be a string (not object/array). */
22001
+ function normalizeChainJsonMetadata(value) {
22002
+ if (typeof value === 'string')
22003
+ return value;
22004
+ if (value == null)
22005
+ return '';
22006
+ if (Array.isArray(value))
22007
+ return value.length === 0 ? '' : JSON.stringify(value);
22008
+ if (typeof value === 'object')
22009
+ return JSON.stringify(value);
22010
+ return String(value);
22011
+ }
22012
+ function toAuthPairs(raw) {
22013
+ if (Array.isArray(raw)) {
22014
+ return raw
22015
+ .filter((entry) => Array.isArray(entry) && entry.length >= 2)
22016
+ .map(([key, weight]) => [String(key), Number(weight)])
22017
+ .filter(([, weight]) => Number.isFinite(weight));
22018
+ }
22019
+ if (raw && typeof raw === 'object') {
22020
+ return Object.entries(raw)
22021
+ .map(([key, weight]) => [String(key), Number(weight)])
22022
+ .filter(([, weight]) => Number.isFinite(weight));
22023
+ }
22024
+ return [];
22025
+ }
22026
+ function toKeyAuthPairs(raw) {
22027
+ if (Array.isArray(raw)) {
22028
+ return raw
22029
+ .filter((entry) => Array.isArray(entry) && entry.length >= 2)
22030
+ .map(([key, weight]) => [String(key), Number(weight)])
22031
+ .filter(([key, weight]) => key.startsWith('STM') && Number.isFinite(weight));
22032
+ }
22033
+ if (raw && typeof raw === 'object') {
22034
+ return Object.entries(raw)
22035
+ .map(([key, weight]) => [String(key), Number(weight)])
22036
+ .filter(([key, weight]) => key.startsWith('STM') && Number.isFinite(weight));
22037
+ }
22038
+ return [];
22039
+ }
22040
+ /** Normalize API authority data (handles object-maps and malformed arrays). */
22041
+ function normalizeAuthoritySource(source) {
22042
+ if (Array.isArray(source) || !source || typeof source !== 'object') {
22043
+ return { weight_threshold: 1, account_auths: [], key_auths: [] };
22044
+ }
22045
+ const obj = source;
22046
+ const weight_threshold = Math.max(1, Number(obj.weight_threshold) || 1);
22047
+ return {
22048
+ weight_threshold,
22049
+ account_auths: toAuthPairs(obj.account_auths),
22050
+ key_auths: toKeyAuthPairs(obj.key_auths),
22051
+ };
22052
+ }
22053
+ function sanitizeAuthority(value, field) {
22054
+ if (value == null || typeof value !== 'object' || Array.isArray(value)) {
22055
+ throw new Error(`Invalid ${field} authority: expected object with weight_threshold, account_auths, key_auths`);
22056
+ }
22057
+ const obj = value;
22058
+ const weight_threshold = Math.max(1, Number(obj.weight_threshold) || 1);
22059
+ const account_auths = toAuthPairs(obj.account_auths);
22060
+ const key_auths = toKeyAuthPairs(obj.key_auths);
22061
+ if (key_auths.length === 0) {
22062
+ throw new Error(`Invalid ${field} authority: key_auths is empty or malformed`);
22063
+ }
22064
+ return { weight_threshold, account_auths, key_auths };
22065
+ }
22066
+ /** Coerce account_update operation payload to chain-safe JSON (for signing and broadcast). */
22067
+ function sanitizeAccountUpdatePayload(payload) {
22068
+ return {
22069
+ account: String(payload.account || ''),
22070
+ owner: sanitizeAuthority(payload.owner, 'owner'),
22071
+ active: sanitizeAuthority(payload.active, 'active'),
22072
+ posting: sanitizeAuthority(payload.posting, 'posting'),
22073
+ memo_key: String(payload.memo_key || ''),
22074
+ json_metadata: normalizeChainJsonMetadata(payload.json_metadata),
22075
+ };
22076
+ }
22077
+ /**
22078
+ * Normalize an operation tuple before signing or JSON broadcast.
22079
+ * Only account_update is rewritten; other operations pass through unchanged.
22080
+ */
22081
+ function normalizeOperationForBroadcast(operation) {
22082
+ if (!Array.isArray(operation) || operation.length !== 2) {
22083
+ return operation;
22084
+ }
22085
+ const [opType, opData] = operation;
22086
+ if (opType !== 'account_update') {
22087
+ return operation;
22088
+ }
22089
+ if (!opData || typeof opData !== 'object' || Array.isArray(opData)) {
22090
+ throw new Error('account_update payload must be an object');
22091
+ }
22092
+ return ['account_update', sanitizeAccountUpdatePayload(opData)];
22093
+ }
22094
+ /** Normalize transaction operations/extensions for JSON broadcast after signing. */
22095
+ function normalizeTransactionForBroadcast(trx) {
22096
+ const operations = Array.isArray(trx.operations) ? trx.operations : [];
22097
+ const extensions = Array.isArray(trx.extensions) ? trx.extensions : [];
22098
+ return {
22099
+ ...trx,
22100
+ operations: operations.map((op) => normalizeOperationForBroadcast(op)),
22101
+ extensions,
22102
+ };
22103
+ }
22104
+ /**
22105
+ * Authority value for binary serialization (fail-fast on array mistaken for object).
22106
+ * Mirrors steem wallet_api::update_account which assigns authority structs, not key_auths arrays.
22107
+ */
22108
+ function resolveAuthorityForSerialize(auth, field) {
22109
+ if (auth == null || auth === '') {
22110
+ throw new Error(`Invalid ${field} authority: value is required`);
22111
+ }
22112
+ if (Array.isArray(auth)) {
22113
+ throw new Error(`Invalid ${field} authority: expected object, got array (wrap key_auths inside an authority object)`);
22114
+ }
22115
+ if (typeof auth !== 'object') {
22116
+ throw new Error(`Invalid ${field} authority: expected object`);
22117
+ }
22118
+ return auth;
22119
+ }
22120
+
21995
22121
  /**
21996
22122
  * Serialize a transaction to binary format for Steem blockchain
21997
22123
  * This is a simplified implementation that handles the basic structure
@@ -22358,21 +22484,21 @@ function serializeAccountUpdate(bb, data) {
22358
22484
  // Optional authorities: 0 = not present, 1 = present then serialize authority
22359
22485
  if (dataObj.owner != null && dataObj.owner !== '') {
22360
22486
  bb.writeUint8(1);
22361
- serializeAuthority(bb, typeof dataObj.owner === 'object' ? dataObj.owner : { weight_threshold: 1, account_auths: [], key_auths: [] });
22487
+ serializeAuthority(bb, resolveAuthorityForSerialize(dataObj.owner, 'owner'));
22362
22488
  }
22363
22489
  else {
22364
22490
  bb.writeUint8(0);
22365
22491
  }
22366
22492
  if (dataObj.active != null && dataObj.active !== '') {
22367
22493
  bb.writeUint8(1);
22368
- serializeAuthority(bb, typeof dataObj.active === 'object' ? dataObj.active : { weight_threshold: 1, account_auths: [], key_auths: [] });
22494
+ serializeAuthority(bb, resolveAuthorityForSerialize(dataObj.active, 'active'));
22369
22495
  }
22370
22496
  else {
22371
22497
  bb.writeUint8(0);
22372
22498
  }
22373
22499
  if (dataObj.posting != null && dataObj.posting !== '') {
22374
22500
  bb.writeUint8(1);
22375
- serializeAuthority(bb, typeof dataObj.posting === 'object' ? dataObj.posting : { weight_threshold: 1, account_auths: [], key_auths: [] });
22501
+ serializeAuthority(bb, resolveAuthorityForSerialize(dataObj.posting, 'posting'));
22376
22502
  }
22377
22503
  else {
22378
22504
  bb.writeUint8(0);
@@ -23020,6 +23146,12 @@ function serializeCustomJson(bb, data) {
23020
23146
  * Serialize Authority
23021
23147
  */
23022
23148
  function serializeAuthority(bb, auth) {
23149
+ if (Array.isArray(auth)) {
23150
+ throw new Error('Invalid authority: expected object, got array');
23151
+ }
23152
+ if (auth == null || typeof auth !== 'object') {
23153
+ throw new Error('Invalid authority: expected object');
23154
+ }
23023
23155
  const authObj = auth;
23024
23156
  bb.writeUint32(authObj.weight_threshold || 1);
23025
23157
  // Account auths (map<string, uint16>)
@@ -23355,17 +23487,18 @@ const Auth = {
23355
23487
  if (Array.isArray(trxObjWithSigs.signatures)) {
23356
23488
  signatures.push(...trxObjWithSigs.signatures.map((sig) => Buffer.isBuffer(sig) ? sig.toString('hex') : String(sig)));
23357
23489
  }
23490
+ const trxObj = trx;
23491
+ const normalizedTrx = normalizeTransactionForBroadcast(trxObj);
23358
23492
  const chainId = getConfig().get('chain_id') || '';
23359
23493
  const cid = Buffer.from(chainId, 'hex');
23360
- const buf = transaction.toBuffer(trx);
23494
+ const buf = transaction.toBuffer(normalizedTrx);
23361
23495
  for (const key of keys) {
23362
23496
  const sig = Signature.signBuffer(Buffer.concat([cid, buf]), key);
23363
23497
  // Use toBuffer() to match old-steem-js behavior
23364
23498
  // The serializer will convert Buffer to hex string when needed
23365
23499
  signatures.push(sig.toBuffer().toString('hex'));
23366
23500
  }
23367
- const trxObj = trx;
23368
- return signed_transaction.toObject(Object.assign(trxObj, { signatures }));
23501
+ return signed_transaction.toObject(Object.assign({}, normalizedTrx, { signatures }));
23369
23502
  }
23370
23503
  };
23371
23504
  // Export individual functions
@@ -23445,6 +23578,12 @@ var auth = /*#__PURE__*/Object.freeze({
23445
23578
  getPublicKey: getPublicKey,
23446
23579
  isPubkey: isPubkey,
23447
23580
  isWif: isWif,
23581
+ normalizeAuthoritySource: normalizeAuthoritySource,
23582
+ normalizeChainJsonMetadata: normalizeChainJsonMetadata,
23583
+ normalizeOperationForBroadcast: normalizeOperationForBroadcast,
23584
+ normalizeTransactionForBroadcast: normalizeTransactionForBroadcast,
23585
+ resolveAuthorityForSerialize: resolveAuthorityForSerialize,
23586
+ sanitizeAccountUpdatePayload: sanitizeAccountUpdatePayload,
23448
23587
  sign: sign$1,
23449
23588
  signTransaction: signTransaction,
23450
23589
  toWif: toWif,
@@ -26253,7 +26392,7 @@ const steem = {
26253
26392
  memo,
26254
26393
  operations,
26255
26394
  utils: utils$3,
26256
- version: '1.0.17',
26395
+ version: '1.0.18',
26257
26396
  config: {
26258
26397
  set: (options) => {
26259
26398
  // If nodes is provided, extract the first node as url for API