@steemit/steem-js 1.0.17 → 1.0.19
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/auth/account-update-chain.d.ts +67 -0
- package/dist/auth/index.d.ts +2 -0
- package/dist/browser.esm.js +199 -40
- package/dist/browser.esm.js.map +1 -1
- package/dist/index.cjs +199 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +199 -40
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +199 -40
- package/dist/index.umd.js.map +1 -1
- package/dist/index.umd.min.js +1 -1
- package/dist/index.umd.min.js.map +1 -1
- package/dist/types/index.d.ts +4 -0
- package/dist/types.d.ts +4 -0
- package/package.json +1 -1
package/dist/index.umd.js
CHANGED
|
@@ -24986,6 +24986,153 @@
|
|
|
24986
24986
|
};
|
|
24987
24987
|
}
|
|
24988
24988
|
|
|
24989
|
+
/**
|
|
24990
|
+
* Chain-safe JSON normalization for `account_update` operations.
|
|
24991
|
+
*
|
|
24992
|
+
* Protocol types (steem/libraries/protocol):
|
|
24993
|
+
* - `authority` — weight_threshold (uint32), account_auths / key_auths (fc::flat_map)
|
|
24994
|
+
* - `account_update_operation` — account, optional owner/active/posting, memo_key, json_metadata (string)
|
|
24995
|
+
*
|
|
24996
|
+
* JSON-RPC (`condenser_api.broadcast_transaction` → fc::from_variant):
|
|
24997
|
+
* - `authority` is a variant_object, not a bare key_auths array.
|
|
24998
|
+
* - `fc::flat_map` serializes as an array of [key, weight] pairs (see fc/container/flat.hpp),
|
|
24999
|
+
* not a JSON object `{ "key": weight }` — object maps cause bad_cast_exception.
|
|
25000
|
+
* - `json_metadata` must be a string (protocol `string`), not a parsed JSON object.
|
|
25001
|
+
*
|
|
25002
|
+
* Binary signing (transaction digest) uses the same logical fields; the serializer packs
|
|
25003
|
+
* flat_maps as sorted on-wire maps (see serializeAuthority in serializer/transaction.ts).
|
|
25004
|
+
*/
|
|
25005
|
+
/**
|
|
25006
|
+
* Coerce `json_metadata` to protocol `string` (FC string field).
|
|
25007
|
+
* Node rejects object/array variants with bad_cast when broadcasting.
|
|
25008
|
+
*/
|
|
25009
|
+
function normalizeChainJsonMetadata(value) {
|
|
25010
|
+
if (typeof value === 'string')
|
|
25011
|
+
return value;
|
|
25012
|
+
if (value == null)
|
|
25013
|
+
return '';
|
|
25014
|
+
if (Array.isArray(value))
|
|
25015
|
+
return value.length === 0 ? '' : JSON.stringify(value);
|
|
25016
|
+
if (typeof value === 'object')
|
|
25017
|
+
return JSON.stringify(value);
|
|
25018
|
+
return String(value);
|
|
25019
|
+
}
|
|
25020
|
+
/**
|
|
25021
|
+
* Parse fc::flat_map JSON (pair array) or mistaken object-map input into pair arrays.
|
|
25022
|
+
* Broadcast output always uses pair arrays per fc::from_variant(flat_map).
|
|
25023
|
+
*/
|
|
25024
|
+
function toAuthPairs(raw) {
|
|
25025
|
+
if (Array.isArray(raw)) {
|
|
25026
|
+
return raw
|
|
25027
|
+
.filter((entry) => Array.isArray(entry) && entry.length >= 2)
|
|
25028
|
+
.map(([key, weight]) => [String(key), Number(weight)])
|
|
25029
|
+
.filter(([, weight]) => Number.isFinite(weight));
|
|
25030
|
+
}
|
|
25031
|
+
if (raw && typeof raw === 'object') {
|
|
25032
|
+
return Object.entries(raw)
|
|
25033
|
+
.map(([key, weight]) => [String(key), Number(weight)])
|
|
25034
|
+
.filter(([, weight]) => Number.isFinite(weight));
|
|
25035
|
+
}
|
|
25036
|
+
return [];
|
|
25037
|
+
}
|
|
25038
|
+
function toKeyAuthPairs(raw) {
|
|
25039
|
+
if (Array.isArray(raw)) {
|
|
25040
|
+
return raw
|
|
25041
|
+
.filter((entry) => Array.isArray(entry) && entry.length >= 2)
|
|
25042
|
+
.map(([key, weight]) => [String(key), Number(weight)])
|
|
25043
|
+
.filter(([key, weight]) => key.startsWith('STM') && Number.isFinite(weight));
|
|
25044
|
+
}
|
|
25045
|
+
if (raw && typeof raw === 'object') {
|
|
25046
|
+
return Object.entries(raw)
|
|
25047
|
+
.map(([key, weight]) => [String(key), Number(weight)])
|
|
25048
|
+
.filter(([key, weight]) => key.startsWith('STM') && Number.isFinite(weight));
|
|
25049
|
+
}
|
|
25050
|
+
return [];
|
|
25051
|
+
}
|
|
25052
|
+
/** Normalize API authority data (get_accounts-style input; accepts pair arrays or object maps). */
|
|
25053
|
+
function normalizeAuthoritySource(source) {
|
|
25054
|
+
if (Array.isArray(source) || !source || typeof source !== 'object') {
|
|
25055
|
+
return { weight_threshold: 1, account_auths: [], key_auths: [] };
|
|
25056
|
+
}
|
|
25057
|
+
const obj = source;
|
|
25058
|
+
const weight_threshold = Math.max(1, Number(obj.weight_threshold) || 1);
|
|
25059
|
+
return {
|
|
25060
|
+
weight_threshold,
|
|
25061
|
+
account_auths: toAuthPairs(obj.account_auths),
|
|
25062
|
+
key_auths: toKeyAuthPairs(obj.key_auths),
|
|
25063
|
+
};
|
|
25064
|
+
}
|
|
25065
|
+
function sanitizeAuthority(value, field) {
|
|
25066
|
+
if (value == null || typeof value !== 'object' || Array.isArray(value)) {
|
|
25067
|
+
throw new Error(`Invalid ${field} authority: expected object with weight_threshold, account_auths, key_auths`);
|
|
25068
|
+
}
|
|
25069
|
+
const obj = value;
|
|
25070
|
+
const weight_threshold = Math.max(1, Number(obj.weight_threshold) || 1);
|
|
25071
|
+
const account_auths = toAuthPairs(obj.account_auths);
|
|
25072
|
+
const key_auths = toKeyAuthPairs(obj.key_auths);
|
|
25073
|
+
if (key_auths.length === 0) {
|
|
25074
|
+
throw new Error(`Invalid ${field} authority: key_auths is empty or malformed`);
|
|
25075
|
+
}
|
|
25076
|
+
return { weight_threshold, account_auths, key_auths };
|
|
25077
|
+
}
|
|
25078
|
+
/**
|
|
25079
|
+
* Coerce account_update operation payload to protocol JSON shape for signing and broadcast.
|
|
25080
|
+
* Emits fc::flat_map fields as pair arrays, not object maps.
|
|
25081
|
+
*/
|
|
25082
|
+
function sanitizeAccountUpdatePayload(payload) {
|
|
25083
|
+
return {
|
|
25084
|
+
account: String(payload.account || ''),
|
|
25085
|
+
owner: sanitizeAuthority(payload.owner, 'owner'),
|
|
25086
|
+
active: sanitizeAuthority(payload.active, 'active'),
|
|
25087
|
+
posting: sanitizeAuthority(payload.posting, 'posting'),
|
|
25088
|
+
memo_key: String(payload.memo_key || ''),
|
|
25089
|
+
json_metadata: normalizeChainJsonMetadata(payload.json_metadata),
|
|
25090
|
+
};
|
|
25091
|
+
}
|
|
25092
|
+
/**
|
|
25093
|
+
* Normalize an operation tuple before signing or JSON broadcast.
|
|
25094
|
+
* Only account_update is rewritten; other operations pass through unchanged.
|
|
25095
|
+
*/
|
|
25096
|
+
function normalizeOperationForBroadcast(operation) {
|
|
25097
|
+
if (!Array.isArray(operation) || operation.length !== 2) {
|
|
25098
|
+
return operation;
|
|
25099
|
+
}
|
|
25100
|
+
const [opType, opData] = operation;
|
|
25101
|
+
if (opType !== 'account_update') {
|
|
25102
|
+
return operation;
|
|
25103
|
+
}
|
|
25104
|
+
if (!opData || typeof opData !== 'object' || Array.isArray(opData)) {
|
|
25105
|
+
throw new Error('account_update payload must be an object');
|
|
25106
|
+
}
|
|
25107
|
+
return ['account_update', sanitizeAccountUpdatePayload(opData)];
|
|
25108
|
+
}
|
|
25109
|
+
/** Normalize transaction operations/extensions for JSON broadcast after signing. */
|
|
25110
|
+
function normalizeTransactionForBroadcast(trx) {
|
|
25111
|
+
const operations = Array.isArray(trx.operations) ? trx.operations : [];
|
|
25112
|
+
const extensions = Array.isArray(trx.extensions) ? trx.extensions : [];
|
|
25113
|
+
return {
|
|
25114
|
+
...trx,
|
|
25115
|
+
operations: operations.map((op) => normalizeOperationForBroadcast(op)),
|
|
25116
|
+
extensions,
|
|
25117
|
+
};
|
|
25118
|
+
}
|
|
25119
|
+
/**
|
|
25120
|
+
* Authority value for binary serialization (fail-fast on array mistaken for object).
|
|
25121
|
+
* Mirrors steem wallet_api::update_account which assigns authority structs, not key_auths arrays.
|
|
25122
|
+
*/
|
|
25123
|
+
function resolveAuthorityForSerialize(auth, field) {
|
|
25124
|
+
if (auth == null || auth === '') {
|
|
25125
|
+
throw new Error(`Invalid ${field} authority: value is required`);
|
|
25126
|
+
}
|
|
25127
|
+
if (Array.isArray(auth)) {
|
|
25128
|
+
throw new Error(`Invalid ${field} authority: expected object, got array (wrap key_auths inside an authority object)`);
|
|
25129
|
+
}
|
|
25130
|
+
if (typeof auth !== 'object') {
|
|
25131
|
+
throw new Error(`Invalid ${field} authority: expected object`);
|
|
25132
|
+
}
|
|
25133
|
+
return auth;
|
|
25134
|
+
}
|
|
25135
|
+
|
|
24989
25136
|
/**
|
|
24990
25137
|
* Serialize a transaction to binary format for Steem blockchain
|
|
24991
25138
|
* This is a simplified implementation that handles the basic structure
|
|
@@ -25343,8 +25490,9 @@
|
|
|
25343
25490
|
writeString(bb, String(dataObj.json_metadata || ''));
|
|
25344
25491
|
}
|
|
25345
25492
|
/**
|
|
25346
|
-
* Serialize
|
|
25347
|
-
*
|
|
25493
|
+
* Serialize account_update_operation (steem_operations.hpp).
|
|
25494
|
+
* JSON fields: account, owner/active/posting (authority objects), memo_key, json_metadata (string).
|
|
25495
|
+
* Optional authorities use a presence byte before serializeAuthority.
|
|
25348
25496
|
*/
|
|
25349
25497
|
function serializeAccountUpdate(bb, data) {
|
|
25350
25498
|
const dataObj = data;
|
|
@@ -25352,21 +25500,21 @@
|
|
|
25352
25500
|
// Optional authorities: 0 = not present, 1 = present then serialize authority
|
|
25353
25501
|
if (dataObj.owner != null && dataObj.owner !== '') {
|
|
25354
25502
|
bb.writeUint8(1);
|
|
25355
|
-
serializeAuthority(bb,
|
|
25503
|
+
serializeAuthority(bb, resolveAuthorityForSerialize(dataObj.owner, 'owner'));
|
|
25356
25504
|
}
|
|
25357
25505
|
else {
|
|
25358
25506
|
bb.writeUint8(0);
|
|
25359
25507
|
}
|
|
25360
25508
|
if (dataObj.active != null && dataObj.active !== '') {
|
|
25361
25509
|
bb.writeUint8(1);
|
|
25362
|
-
serializeAuthority(bb,
|
|
25510
|
+
serializeAuthority(bb, resolveAuthorityForSerialize(dataObj.active, 'active'));
|
|
25363
25511
|
}
|
|
25364
25512
|
else {
|
|
25365
25513
|
bb.writeUint8(0);
|
|
25366
25514
|
}
|
|
25367
25515
|
if (dataObj.posting != null && dataObj.posting !== '') {
|
|
25368
25516
|
bb.writeUint8(1);
|
|
25369
|
-
serializeAuthority(bb,
|
|
25517
|
+
serializeAuthority(bb, resolveAuthorityForSerialize(dataObj.posting, 'posting'));
|
|
25370
25518
|
}
|
|
25371
25519
|
else {
|
|
25372
25520
|
bb.writeUint8(0);
|
|
@@ -26011,46 +26159,50 @@
|
|
|
26011
26159
|
writeString(bb, String(dataObj.json || '{}'));
|
|
26012
26160
|
}
|
|
26013
26161
|
/**
|
|
26014
|
-
*
|
|
26162
|
+
* Read authority map fields for binary packing (on-wire sorted flat_map).
|
|
26163
|
+
* JSON-RPC uses fc::flat_map → array of [key, weight] pairs; object maps are accepted
|
|
26164
|
+
* here only so callers that forgot to normalize still sign the intended keys.
|
|
26165
|
+
*/
|
|
26166
|
+
function authorityMapEntries(raw) {
|
|
26167
|
+
if (Array.isArray(raw)) {
|
|
26168
|
+
return raw
|
|
26169
|
+
.filter((entry) => Array.isArray(entry) && entry.length >= 2)
|
|
26170
|
+
.map(([key, weight]) => [String(key), Number(weight)])
|
|
26171
|
+
.filter(([, weight]) => Number.isFinite(weight));
|
|
26172
|
+
}
|
|
26173
|
+
if (raw && typeof raw === 'object') {
|
|
26174
|
+
return Object.entries(raw)
|
|
26175
|
+
.map(([key, weight]) => [String(key), Number(weight)])
|
|
26176
|
+
.filter(([, weight]) => Number.isFinite(weight));
|
|
26177
|
+
}
|
|
26178
|
+
return [];
|
|
26179
|
+
}
|
|
26180
|
+
/**
|
|
26181
|
+
* Serialize steem::protocol::authority (weight_threshold + sorted account/key flat_maps).
|
|
26015
26182
|
*/
|
|
26016
26183
|
function serializeAuthority(bb, auth) {
|
|
26184
|
+
if (Array.isArray(auth)) {
|
|
26185
|
+
throw new Error('Invalid authority: expected object, got array');
|
|
26186
|
+
}
|
|
26187
|
+
if (auth == null || typeof auth !== 'object') {
|
|
26188
|
+
throw new Error('Invalid authority: expected object');
|
|
26189
|
+
}
|
|
26017
26190
|
const authObj = auth;
|
|
26018
26191
|
bb.writeUint32(authObj.weight_threshold || 1);
|
|
26019
26192
|
// Account auths (map<string, uint16>)
|
|
26020
|
-
const accountAuths = (
|
|
26021
|
-
// Maps in Steem serialization are sorted by key
|
|
26022
|
-
const accountAuthsArray = accountAuths;
|
|
26023
|
-
accountAuthsArray.sort((a, b) => {
|
|
26024
|
-
const aKey = Array.isArray(a) && a[0] ? String(a[0]) : '';
|
|
26025
|
-
const bKey = Array.isArray(b) && b[0] ? String(b[0]) : '';
|
|
26026
|
-
return aKey.localeCompare(bKey);
|
|
26027
|
-
});
|
|
26193
|
+
const accountAuths = authorityMapEntries(authObj.account_auths).sort((a, b) => a[0].localeCompare(b[0]));
|
|
26028
26194
|
bb.writeVarint32(accountAuths.length);
|
|
26029
|
-
for (const
|
|
26030
|
-
|
|
26031
|
-
|
|
26032
|
-
bb.writeUint16(authEntry[1]);
|
|
26033
|
-
}
|
|
26195
|
+
for (const [account, weight] of accountAuths) {
|
|
26196
|
+
writeString(bb, account);
|
|
26197
|
+
bb.writeUint16(weight);
|
|
26034
26198
|
}
|
|
26035
26199
|
// Key auths (map<public_key, uint16>)
|
|
26036
|
-
const keyAuths = (
|
|
26037
|
-
// Maps in Steem serialization are sorted by key (public key string)
|
|
26038
|
-
// But serialized as bytes. Usually sorting by string representation of public key works.
|
|
26039
|
-
const keyAuthsArray = keyAuths;
|
|
26040
|
-
keyAuthsArray.sort((a, b) => {
|
|
26041
|
-
const aKey = Array.isArray(a) && a[0] ? String(a[0]) : '';
|
|
26042
|
-
const bKey = Array.isArray(b) && b[0] ? String(b[0]) : '';
|
|
26043
|
-
return aKey.localeCompare(bKey);
|
|
26044
|
-
});
|
|
26200
|
+
const keyAuths = authorityMapEntries(authObj.key_auths).sort((a, b) => a[0].localeCompare(b[0]));
|
|
26045
26201
|
bb.writeVarint32(keyAuths.length);
|
|
26046
|
-
for (const
|
|
26047
|
-
|
|
26048
|
-
|
|
26049
|
-
|
|
26050
|
-
const pubKey = PublicKey.fromStringOrThrow(keyStr);
|
|
26051
|
-
bb.append(pubKey.toBuffer());
|
|
26052
|
-
bb.writeUint16(weight);
|
|
26053
|
-
}
|
|
26202
|
+
for (const [keyStr, weight] of keyAuths) {
|
|
26203
|
+
const pubKey = PublicKey.fromStringOrThrow(keyStr);
|
|
26204
|
+
bb.append(pubKey.toBuffer());
|
|
26205
|
+
bb.writeUint16(weight);
|
|
26054
26206
|
}
|
|
26055
26207
|
}
|
|
26056
26208
|
/**
|
|
@@ -26349,17 +26501,18 @@
|
|
|
26349
26501
|
if (Array.isArray(trxObjWithSigs.signatures)) {
|
|
26350
26502
|
signatures.push(...trxObjWithSigs.signatures.map((sig) => buffer.Buffer.isBuffer(sig) ? sig.toString('hex') : String(sig)));
|
|
26351
26503
|
}
|
|
26504
|
+
const trxObj = trx;
|
|
26505
|
+
const normalizedTrx = normalizeTransactionForBroadcast(trxObj);
|
|
26352
26506
|
const chainId = getConfig().get('chain_id') || '';
|
|
26353
26507
|
const cid = buffer.Buffer.from(chainId, 'hex');
|
|
26354
|
-
const buf = transaction.toBuffer(
|
|
26508
|
+
const buf = transaction.toBuffer(normalizedTrx);
|
|
26355
26509
|
for (const key of keys) {
|
|
26356
26510
|
const sig = Signature.signBuffer(buffer.Buffer.concat([cid, buf]), key);
|
|
26357
26511
|
// Use toBuffer() to match old-steem-js behavior
|
|
26358
26512
|
// The serializer will convert Buffer to hex string when needed
|
|
26359
26513
|
signatures.push(sig.toBuffer().toString('hex'));
|
|
26360
26514
|
}
|
|
26361
|
-
|
|
26362
|
-
return signed_transaction.toObject(Object.assign(trxObj, { signatures }));
|
|
26515
|
+
return signed_transaction.toObject(Object.assign({}, normalizedTrx, { signatures }));
|
|
26363
26516
|
}
|
|
26364
26517
|
};
|
|
26365
26518
|
// Export individual functions
|
|
@@ -26439,6 +26592,12 @@
|
|
|
26439
26592
|
getPublicKey: getPublicKey,
|
|
26440
26593
|
isPubkey: isPubkey,
|
|
26441
26594
|
isWif: isWif,
|
|
26595
|
+
normalizeAuthoritySource: normalizeAuthoritySource,
|
|
26596
|
+
normalizeChainJsonMetadata: normalizeChainJsonMetadata,
|
|
26597
|
+
normalizeOperationForBroadcast: normalizeOperationForBroadcast,
|
|
26598
|
+
normalizeTransactionForBroadcast: normalizeTransactionForBroadcast,
|
|
26599
|
+
resolveAuthorityForSerialize: resolveAuthorityForSerialize,
|
|
26600
|
+
sanitizeAccountUpdatePayload: sanitizeAccountUpdatePayload,
|
|
26442
26601
|
sign: sign$1,
|
|
26443
26602
|
signTransaction: signTransaction,
|
|
26444
26603
|
toWif: toWif,
|
|
@@ -29260,7 +29419,7 @@
|
|
|
29260
29419
|
operations,
|
|
29261
29420
|
utils: utils$n,
|
|
29262
29421
|
...crypto$1,
|
|
29263
|
-
version: '1.0.
|
|
29422
|
+
version: '1.0.19',
|
|
29264
29423
|
config: {
|
|
29265
29424
|
set: (options) => {
|
|
29266
29425
|
// If nodes is provided, extract the first node as url for API
|