@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.js CHANGED
@@ -21972,6 +21972,132 @@ if (typeof BigInt === "function") {
21972
21972
  };
21973
21973
  }
21974
21974
 
21975
+ /**
21976
+ * Chain-safe JSON normalization for account_update operations.
21977
+ * Matches steem::protocol::account_update_operation and authority (FC_REFLECT).
21978
+ * Broadcast via JSON-RPC uses fc::from_variant; malformed shapes cause bad_cast_exception.
21979
+ */
21980
+ /** Steem broadcast JSON requires json_metadata to be a string (not object/array). */
21981
+ function normalizeChainJsonMetadata(value) {
21982
+ if (typeof value === 'string')
21983
+ return value;
21984
+ if (value == null)
21985
+ return '';
21986
+ if (Array.isArray(value))
21987
+ return value.length === 0 ? '' : JSON.stringify(value);
21988
+ if (typeof value === 'object')
21989
+ return JSON.stringify(value);
21990
+ return String(value);
21991
+ }
21992
+ function toAuthPairs(raw) {
21993
+ if (Array.isArray(raw)) {
21994
+ return raw
21995
+ .filter((entry) => Array.isArray(entry) && entry.length >= 2)
21996
+ .map(([key, weight]) => [String(key), Number(weight)])
21997
+ .filter(([, weight]) => Number.isFinite(weight));
21998
+ }
21999
+ if (raw && typeof raw === 'object') {
22000
+ return Object.entries(raw)
22001
+ .map(([key, weight]) => [String(key), Number(weight)])
22002
+ .filter(([, weight]) => Number.isFinite(weight));
22003
+ }
22004
+ return [];
22005
+ }
22006
+ function toKeyAuthPairs(raw) {
22007
+ if (Array.isArray(raw)) {
22008
+ return raw
22009
+ .filter((entry) => Array.isArray(entry) && entry.length >= 2)
22010
+ .map(([key, weight]) => [String(key), Number(weight)])
22011
+ .filter(([key, weight]) => key.startsWith('STM') && Number.isFinite(weight));
22012
+ }
22013
+ if (raw && typeof raw === 'object') {
22014
+ return Object.entries(raw)
22015
+ .map(([key, weight]) => [String(key), Number(weight)])
22016
+ .filter(([key, weight]) => key.startsWith('STM') && Number.isFinite(weight));
22017
+ }
22018
+ return [];
22019
+ }
22020
+ /** Normalize API authority data (handles object-maps and malformed arrays). */
22021
+ function normalizeAuthoritySource(source) {
22022
+ if (Array.isArray(source) || !source || typeof source !== 'object') {
22023
+ return { weight_threshold: 1, account_auths: [], key_auths: [] };
22024
+ }
22025
+ const obj = source;
22026
+ const weight_threshold = Math.max(1, Number(obj.weight_threshold) || 1);
22027
+ return {
22028
+ weight_threshold,
22029
+ account_auths: toAuthPairs(obj.account_auths),
22030
+ key_auths: toKeyAuthPairs(obj.key_auths),
22031
+ };
22032
+ }
22033
+ function sanitizeAuthority(value, field) {
22034
+ if (value == null || typeof value !== 'object' || Array.isArray(value)) {
22035
+ throw new Error(`Invalid ${field} authority: expected object with weight_threshold, account_auths, key_auths`);
22036
+ }
22037
+ const obj = value;
22038
+ const weight_threshold = Math.max(1, Number(obj.weight_threshold) || 1);
22039
+ const account_auths = toAuthPairs(obj.account_auths);
22040
+ const key_auths = toKeyAuthPairs(obj.key_auths);
22041
+ if (key_auths.length === 0) {
22042
+ throw new Error(`Invalid ${field} authority: key_auths is empty or malformed`);
22043
+ }
22044
+ return { weight_threshold, account_auths, key_auths };
22045
+ }
22046
+ /** Coerce account_update operation payload to chain-safe JSON (for signing and broadcast). */
22047
+ function sanitizeAccountUpdatePayload(payload) {
22048
+ return {
22049
+ account: String(payload.account || ''),
22050
+ owner: sanitizeAuthority(payload.owner, 'owner'),
22051
+ active: sanitizeAuthority(payload.active, 'active'),
22052
+ posting: sanitizeAuthority(payload.posting, 'posting'),
22053
+ memo_key: String(payload.memo_key || ''),
22054
+ json_metadata: normalizeChainJsonMetadata(payload.json_metadata),
22055
+ };
22056
+ }
22057
+ /**
22058
+ * Normalize an operation tuple before signing or JSON broadcast.
22059
+ * Only account_update is rewritten; other operations pass through unchanged.
22060
+ */
22061
+ function normalizeOperationForBroadcast(operation) {
22062
+ if (!Array.isArray(operation) || operation.length !== 2) {
22063
+ return operation;
22064
+ }
22065
+ const [opType, opData] = operation;
22066
+ if (opType !== 'account_update') {
22067
+ return operation;
22068
+ }
22069
+ if (!opData || typeof opData !== 'object' || Array.isArray(opData)) {
22070
+ throw new Error('account_update payload must be an object');
22071
+ }
22072
+ return ['account_update', sanitizeAccountUpdatePayload(opData)];
22073
+ }
22074
+ /** Normalize transaction operations/extensions for JSON broadcast after signing. */
22075
+ function normalizeTransactionForBroadcast(trx) {
22076
+ const operations = Array.isArray(trx.operations) ? trx.operations : [];
22077
+ const extensions = Array.isArray(trx.extensions) ? trx.extensions : [];
22078
+ return {
22079
+ ...trx,
22080
+ operations: operations.map((op) => normalizeOperationForBroadcast(op)),
22081
+ extensions,
22082
+ };
22083
+ }
22084
+ /**
22085
+ * Authority value for binary serialization (fail-fast on array mistaken for object).
22086
+ * Mirrors steem wallet_api::update_account which assigns authority structs, not key_auths arrays.
22087
+ */
22088
+ function resolveAuthorityForSerialize(auth, field) {
22089
+ if (auth == null || auth === '') {
22090
+ throw new Error(`Invalid ${field} authority: value is required`);
22091
+ }
22092
+ if (Array.isArray(auth)) {
22093
+ throw new Error(`Invalid ${field} authority: expected object, got array (wrap key_auths inside an authority object)`);
22094
+ }
22095
+ if (typeof auth !== 'object') {
22096
+ throw new Error(`Invalid ${field} authority: expected object`);
22097
+ }
22098
+ return auth;
22099
+ }
22100
+
21975
22101
  /**
21976
22102
  * Serialize a transaction to binary format for Steem blockchain
21977
22103
  * This is a simplified implementation that handles the basic structure
@@ -22338,21 +22464,21 @@ function serializeAccountUpdate(bb, data) {
22338
22464
  // Optional authorities: 0 = not present, 1 = present then serialize authority
22339
22465
  if (dataObj.owner != null && dataObj.owner !== '') {
22340
22466
  bb.writeUint8(1);
22341
- serializeAuthority(bb, typeof dataObj.owner === 'object' ? dataObj.owner : { weight_threshold: 1, account_auths: [], key_auths: [] });
22467
+ serializeAuthority(bb, resolveAuthorityForSerialize(dataObj.owner, 'owner'));
22342
22468
  }
22343
22469
  else {
22344
22470
  bb.writeUint8(0);
22345
22471
  }
22346
22472
  if (dataObj.active != null && dataObj.active !== '') {
22347
22473
  bb.writeUint8(1);
22348
- serializeAuthority(bb, typeof dataObj.active === 'object' ? dataObj.active : { weight_threshold: 1, account_auths: [], key_auths: [] });
22474
+ serializeAuthority(bb, resolveAuthorityForSerialize(dataObj.active, 'active'));
22349
22475
  }
22350
22476
  else {
22351
22477
  bb.writeUint8(0);
22352
22478
  }
22353
22479
  if (dataObj.posting != null && dataObj.posting !== '') {
22354
22480
  bb.writeUint8(1);
22355
- serializeAuthority(bb, typeof dataObj.posting === 'object' ? dataObj.posting : { weight_threshold: 1, account_auths: [], key_auths: [] });
22481
+ serializeAuthority(bb, resolveAuthorityForSerialize(dataObj.posting, 'posting'));
22356
22482
  }
22357
22483
  else {
22358
22484
  bb.writeUint8(0);
@@ -23000,6 +23126,12 @@ function serializeCustomJson(bb, data) {
23000
23126
  * Serialize Authority
23001
23127
  */
23002
23128
  function serializeAuthority(bb, auth) {
23129
+ if (Array.isArray(auth)) {
23130
+ throw new Error('Invalid authority: expected object, got array');
23131
+ }
23132
+ if (auth == null || typeof auth !== 'object') {
23133
+ throw new Error('Invalid authority: expected object');
23134
+ }
23003
23135
  const authObj = auth;
23004
23136
  bb.writeUint32(authObj.weight_threshold || 1);
23005
23137
  // Account auths (map<string, uint16>)
@@ -23335,17 +23467,18 @@ const Auth = {
23335
23467
  if (Array.isArray(trxObjWithSigs.signatures)) {
23336
23468
  signatures.push(...trxObjWithSigs.signatures.map((sig) => Buffer.isBuffer(sig) ? sig.toString('hex') : String(sig)));
23337
23469
  }
23470
+ const trxObj = trx;
23471
+ const normalizedTrx = normalizeTransactionForBroadcast(trxObj);
23338
23472
  const chainId = getConfig().get('chain_id') || '';
23339
23473
  const cid = Buffer.from(chainId, 'hex');
23340
- const buf = transaction.toBuffer(trx);
23474
+ const buf = transaction.toBuffer(normalizedTrx);
23341
23475
  for (const key of keys) {
23342
23476
  const sig = Signature.signBuffer(Buffer.concat([cid, buf]), key);
23343
23477
  // Use toBuffer() to match old-steem-js behavior
23344
23478
  // The serializer will convert Buffer to hex string when needed
23345
23479
  signatures.push(sig.toBuffer().toString('hex'));
23346
23480
  }
23347
- const trxObj = trx;
23348
- return signed_transaction.toObject(Object.assign(trxObj, { signatures }));
23481
+ return signed_transaction.toObject(Object.assign({}, normalizedTrx, { signatures }));
23349
23482
  }
23350
23483
  };
23351
23484
  // Export individual functions
@@ -23425,6 +23558,12 @@ const auth = /*#__PURE__*/Object.freeze({
23425
23558
  getPublicKey: getPublicKey,
23426
23559
  isPubkey: isPubkey,
23427
23560
  isWif: isWif,
23561
+ normalizeAuthoritySource: normalizeAuthoritySource,
23562
+ normalizeChainJsonMetadata: normalizeChainJsonMetadata,
23563
+ normalizeOperationForBroadcast: normalizeOperationForBroadcast,
23564
+ normalizeTransactionForBroadcast: normalizeTransactionForBroadcast,
23565
+ resolveAuthorityForSerialize: resolveAuthorityForSerialize,
23566
+ sanitizeAccountUpdatePayload: sanitizeAccountUpdatePayload,
23428
23567
  sign: sign$1,
23429
23568
  signTransaction: signTransaction,
23430
23569
  toWif: toWif,
@@ -26233,7 +26372,7 @@ const steem = {
26233
26372
  memo,
26234
26373
  operations,
26235
26374
  utils: utils$3,
26236
- version: '1.0.17',
26375
+ version: '1.0.18',
26237
26376
  config: {
26238
26377
  set: (options) => {
26239
26378
  // If nodes is provided, extract the first node as url for API