Some checks failed
morphit-release / Build + publish release tarball (push) Has been cancelled
461 lines
16 KiB
JavaScript
461 lines
16 KiB
JavaScript
"use strict";
|
|
/**
|
|
* @file Blurt protocol serialization.
|
|
* @author Johan Nordberg <code@johan-nordberg.com>
|
|
* @license
|
|
* Copyright (c) 2017 Johan Nordberg. All Rights Reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without modification,
|
|
* are permitted provided that the following conditions are met:
|
|
*
|
|
* 1. Redistribution of source code must retain the above copyright notice, this
|
|
* list of conditions and the following disclaimer.
|
|
*
|
|
* 2. Redistribution in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
* and/or other materials provided with the distribution.
|
|
*
|
|
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software without
|
|
* specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
* You acknowledge that this software is not designed, licensed or intended for use
|
|
* in the design, construction, operation or maintenance of any military facility.
|
|
*/
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.Types = void 0;
|
|
const crypto_1 = require("../crypto");
|
|
const asset_1 = require("./asset");
|
|
const misc_1 = require("./misc");
|
|
// The package's Node entry point still calls deprecated `Buffer()`; this build has the same API.
|
|
const RuntimeByteBuffer = require('bytebuffer/dist/bytebuffer');
|
|
const PublicKeySerializer = (buffer, data) => {
|
|
if (data === null || (typeof data === 'string' && data.endsWith('1111111111111111111111111111111114T1Anm'))) {
|
|
buffer.append(Buffer.alloc(33, 0));
|
|
}
|
|
else {
|
|
buffer.append(crypto_1.PublicKey.from(data).key);
|
|
}
|
|
};
|
|
/** Basic */
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
const VoidSerializer = (buffer) => {
|
|
throw new Error('Void can not be serialized');
|
|
};
|
|
const StringSerializer = (buffer, data) => {
|
|
buffer.writeVString(data);
|
|
};
|
|
const DateSerializer = (buffer, data) => {
|
|
buffer.writeUint32(Math.floor(new Date(data + 'Z').getTime() / 1000));
|
|
};
|
|
const BooleanSerializer = (buffer, data) => {
|
|
buffer.writeByte(data ? 1 : 0);
|
|
};
|
|
// eslint-disable-next-line max-len
|
|
const FlatMapSerializer = (keySerializer, valueSerializer) => (buffer, data) => {
|
|
buffer.writeVarint32(data.length);
|
|
for (const [key, value] of data) {
|
|
keySerializer(buffer, key);
|
|
valueSerializer(buffer, value);
|
|
}
|
|
};
|
|
const ArraySerializer = (itemSerializer) => (buffer, data) => {
|
|
buffer.writeVarint32(data.length);
|
|
for (const item of data) {
|
|
itemSerializer(buffer, item);
|
|
}
|
|
};
|
|
const StaticVariantSerializer = (itemSerializers) => (buffer, data) => {
|
|
const [id, item] = data;
|
|
buffer.writeVarint32(id);
|
|
itemSerializers[id](buffer, item);
|
|
};
|
|
/** Serialize asset exactly in protocol smallest units. */
|
|
const AssetSerializer = (buffer, data) => {
|
|
const asset = asset_1.Asset.from(data).symbols();
|
|
const precision = asset.getPrecision();
|
|
buffer.writeInt64(RuntimeByteBuffer.Long.fromString(asset.toSmallestUnitString()));
|
|
buffer.writeUint8(precision);
|
|
for (let i = 0; i < 7; i++) {
|
|
buffer.writeUint8(asset.symbol.charCodeAt(i) || 0);
|
|
}
|
|
};
|
|
const BinarySerializer = (size) => (buffer, data) => {
|
|
data = misc_1.HexBuffer.from(data);
|
|
const len = data.buffer.length;
|
|
if (size) {
|
|
if (len !== size) {
|
|
throw new Error(`Unable to serialize binary. Expected ${size} bytes, got ${len}`);
|
|
}
|
|
}
|
|
else {
|
|
buffer.writeVarint32(len);
|
|
}
|
|
buffer.append(data.buffer);
|
|
};
|
|
const VariableBinarySerializer = BinarySerializer();
|
|
/** Int */
|
|
const Int8Serializer = (buffer, data) => {
|
|
buffer.writeInt8(data);
|
|
};
|
|
const Int16Serializer = (buffer, data) => {
|
|
buffer.writeInt16(data);
|
|
};
|
|
const Int32Serializer = (buffer, data) => {
|
|
buffer.writeInt32(data);
|
|
};
|
|
const Int64Serializer = (buffer, data) => {
|
|
buffer.writeInt64(data);
|
|
};
|
|
/** Uint */
|
|
const UInt8Serializer = (buffer, data) => {
|
|
buffer.writeUint8(data);
|
|
};
|
|
const UInt16Serializer = (buffer, data) => {
|
|
buffer.writeUint16(data);
|
|
};
|
|
const UInt32Serializer = (buffer, data) => {
|
|
buffer.writeUint32(data);
|
|
};
|
|
const UInt64Serializer = (buffer, data) => {
|
|
buffer.writeUint64(data);
|
|
};
|
|
/** Serializer */
|
|
const OperationDataSerializer = (operationId, definitions) => {
|
|
const objectSerializer = ObjectSerializer(definitions);
|
|
return (buffer, data) => {
|
|
buffer.writeVarint32(operationId);
|
|
objectSerializer(buffer, data);
|
|
};
|
|
};
|
|
// eslint-disable-next-line max-len
|
|
const ObjectSerializer = (keySerializers) => (buffer, data) => {
|
|
for (const [key, serializer] of keySerializers) {
|
|
try {
|
|
serializer(buffer, data[key]);
|
|
}
|
|
catch (error) {
|
|
error.message = `${key}: ${error.message}`;
|
|
throw error;
|
|
}
|
|
}
|
|
};
|
|
const EncryptedMemoSerializer = ObjectSerializer([
|
|
['from', PublicKeySerializer],
|
|
['to', PublicKeySerializer],
|
|
['nonce', UInt64Serializer],
|
|
['check', UInt32Serializer],
|
|
['encrypted', BinarySerializer()]
|
|
]);
|
|
const OptionalSerializer = (valueSerializer) => (buffer, data) => {
|
|
if (data) {
|
|
buffer.writeByte(1);
|
|
valueSerializer(buffer, data);
|
|
}
|
|
else {
|
|
buffer.writeByte(0);
|
|
}
|
|
};
|
|
const AuthoritySerializer = ObjectSerializer([
|
|
['weight_threshold', UInt32Serializer],
|
|
['account_auths', FlatMapSerializer(StringSerializer, UInt16Serializer)],
|
|
['key_auths', FlatMapSerializer(PublicKeySerializer, UInt16Serializer)]
|
|
]);
|
|
const BeneficiarySerializer = ObjectSerializer([
|
|
['account', StringSerializer],
|
|
['weight', UInt16Serializer]
|
|
]);
|
|
const WitnessUpdatePropertiesSerializer = ObjectSerializer([
|
|
['account_creation_fee', AssetSerializer],
|
|
// ['account_subsidy_budget', UInt32Serializer],
|
|
// ['account_subsidy_decay', UInt32Serializer],
|
|
// ['bandwidth_kbytes_fee', AssetSerializer],
|
|
['maximum_block_size', UInt32Serializer]
|
|
// ['operation_flat_fee', AssetSerializer],
|
|
// ['proposal_fee', AssetSerializer],
|
|
]);
|
|
/**
|
|
* START | Operation Serializers
|
|
*/
|
|
const OperationSerializers = {};
|
|
OperationSerializers.account_create = OperationDataSerializer(5, [
|
|
['fee', AssetSerializer],
|
|
['creator', StringSerializer],
|
|
['new_account_name', StringSerializer],
|
|
['owner', AuthoritySerializer],
|
|
['active', AuthoritySerializer],
|
|
['posting', AuthoritySerializer],
|
|
['memo_key', PublicKeySerializer],
|
|
['json_metadata', StringSerializer]
|
|
]);
|
|
/** update for blurt's account_update */
|
|
OperationSerializers.account_update = OperationDataSerializer(6, [
|
|
['account', StringSerializer],
|
|
['owner', OptionalSerializer(AuthoritySerializer)],
|
|
['active', OptionalSerializer(AuthoritySerializer)],
|
|
['posting', OptionalSerializer(AuthoritySerializer)],
|
|
['memo_key', OptionalSerializer(PublicKeySerializer)],
|
|
['json_metadata', StringSerializer],
|
|
['posting_json_metadata', StringSerializer],
|
|
['extensions', ArraySerializer(StringSerializer)]
|
|
]);
|
|
OperationSerializers.account_witness_vote = OperationDataSerializer(8, [
|
|
['account', StringSerializer],
|
|
['witness', StringSerializer],
|
|
['approve', BooleanSerializer]
|
|
]);
|
|
OperationSerializers.account_witness_proxy = OperationDataSerializer(9, [
|
|
['account', StringSerializer],
|
|
['proxy', StringSerializer]
|
|
]);
|
|
OperationSerializers.change_recovery_account = OperationDataSerializer(19, [
|
|
['account_to_recover', StringSerializer],
|
|
['new_recovery_account', StringSerializer],
|
|
['extensions', ArraySerializer(StringSerializer)]
|
|
]);
|
|
OperationSerializers.claim_account = OperationDataSerializer(15, [
|
|
['creator', StringSerializer],
|
|
['fee', AssetSerializer],
|
|
['extensions', ArraySerializer(VoidSerializer)]
|
|
]);
|
|
OperationSerializers.create_claimed_account = OperationDataSerializer(16, [
|
|
['creator', StringSerializer],
|
|
['new_account_name', StringSerializer],
|
|
['owner', AuthoritySerializer],
|
|
['active', AuthoritySerializer],
|
|
['posting', AuthoritySerializer],
|
|
['memo_key', PublicKeySerializer],
|
|
['json_metadata', StringSerializer],
|
|
['extensions', ArraySerializer(VoidSerializer)]
|
|
]);
|
|
OperationSerializers.claim_reward_balance = OperationDataSerializer(31, [
|
|
['account', StringSerializer],
|
|
['reward_blurt', AssetSerializer],
|
|
['reward_vests', AssetSerializer]
|
|
]);
|
|
OperationSerializers.cancel_transfer_from_savings = OperationDataSerializer(26, [
|
|
['from', StringSerializer],
|
|
['request_id', UInt32Serializer]
|
|
]);
|
|
OperationSerializers.comment = OperationDataSerializer(1, [
|
|
['parent_author', StringSerializer],
|
|
['parent_permlink', StringSerializer],
|
|
['author', StringSerializer],
|
|
['permlink', StringSerializer],
|
|
['title', StringSerializer],
|
|
['body', StringSerializer],
|
|
['json_metadata', StringSerializer]
|
|
]);
|
|
OperationSerializers.comment_options = OperationDataSerializer(13, [
|
|
['author', StringSerializer],
|
|
['permlink', StringSerializer],
|
|
['max_accepted_payout', AssetSerializer],
|
|
['allow_votes', BooleanSerializer],
|
|
['allow_curation_rewards', BooleanSerializer],
|
|
[
|
|
'extensions',
|
|
ArraySerializer(StaticVariantSerializer([
|
|
ObjectSerializer([
|
|
['beneficiaries', ArraySerializer(BeneficiarySerializer)]
|
|
]),
|
|
ObjectSerializer([
|
|
['percent_blurt', UInt16Serializer]
|
|
])
|
|
]))
|
|
]
|
|
]);
|
|
OperationSerializers.custom_json = OperationDataSerializer(12, [
|
|
['required_auths', ArraySerializer(StringSerializer)],
|
|
['required_posting_auths', ArraySerializer(StringSerializer)],
|
|
['id', StringSerializer],
|
|
['json', StringSerializer]
|
|
]);
|
|
OperationSerializers.delete_comment = OperationDataSerializer(11, [
|
|
['author', StringSerializer],
|
|
['permlink', StringSerializer]
|
|
]);
|
|
OperationSerializers.delegate_vesting_shares = OperationDataSerializer(32, [
|
|
['delegator', StringSerializer],
|
|
['delegatee', StringSerializer],
|
|
['vesting_shares', AssetSerializer]
|
|
]);
|
|
OperationSerializers.escrow_transfer = OperationDataSerializer(20, [
|
|
['from', StringSerializer],
|
|
['to', StringSerializer],
|
|
['blurt_amount', AssetSerializer],
|
|
['escrow_id', UInt32Serializer],
|
|
['agent', StringSerializer],
|
|
['fee', AssetSerializer],
|
|
['json_meta', StringSerializer],
|
|
['ratification_deadline', DateSerializer],
|
|
['escrow_expiration', DateSerializer]
|
|
]);
|
|
OperationSerializers.escrow_approve = OperationDataSerializer(23, [
|
|
['from', StringSerializer],
|
|
['to', StringSerializer],
|
|
['agent', StringSerializer],
|
|
['who', StringSerializer],
|
|
['escrow_id', UInt32Serializer],
|
|
['approve', BooleanSerializer]
|
|
]);
|
|
OperationSerializers.escrow_dispute = OperationDataSerializer(21, [
|
|
['from', StringSerializer],
|
|
['to', StringSerializer],
|
|
['agent', StringSerializer],
|
|
['who', StringSerializer],
|
|
['escrow_id', UInt32Serializer]
|
|
]);
|
|
OperationSerializers.escrow_release = OperationDataSerializer(22, [
|
|
['from', StringSerializer],
|
|
['to', StringSerializer],
|
|
['agent', StringSerializer],
|
|
['who', StringSerializer],
|
|
['receiver', StringSerializer],
|
|
['escrow_id', UInt32Serializer],
|
|
['blurt_amount', AssetSerializer]
|
|
]);
|
|
OperationSerializers.transfer = OperationDataSerializer(2, [
|
|
['from', StringSerializer],
|
|
['to', StringSerializer],
|
|
['amount', AssetSerializer],
|
|
['memo', StringSerializer]
|
|
]);
|
|
OperationSerializers.transfer_to_vesting = OperationDataSerializer(3, [
|
|
['from', StringSerializer],
|
|
['to', StringSerializer],
|
|
['amount', AssetSerializer]
|
|
]);
|
|
OperationSerializers.withdraw_vesting = OperationDataSerializer(4, [
|
|
['account', StringSerializer],
|
|
['vesting_shares', AssetSerializer]
|
|
]);
|
|
OperationSerializers.set_withdraw_vesting_route = OperationDataSerializer(14, [
|
|
['from_account', StringSerializer],
|
|
['to_account', StringSerializer],
|
|
['percent', UInt16Serializer],
|
|
['auto_vest', BooleanSerializer]
|
|
]);
|
|
OperationSerializers.transfer_to_savings = OperationDataSerializer(24, [
|
|
['from', StringSerializer],
|
|
['to', StringSerializer],
|
|
['amount', AssetSerializer],
|
|
['memo', StringSerializer]
|
|
]);
|
|
OperationSerializers.transfer_from_savings = OperationDataSerializer(25, [
|
|
['from', StringSerializer],
|
|
['request_id', UInt32Serializer],
|
|
['to', StringSerializer],
|
|
['amount', AssetSerializer],
|
|
['memo', StringSerializer]
|
|
]);
|
|
OperationSerializers.vote = OperationDataSerializer(0, [
|
|
['voter', StringSerializer],
|
|
['author', StringSerializer],
|
|
['permlink', StringSerializer],
|
|
['weight', Int16Serializer]
|
|
]);
|
|
OperationSerializers.witness_update = OperationDataSerializer(7, [
|
|
['owner', StringSerializer],
|
|
['url', StringSerializer],
|
|
['block_signing_key', PublicKeySerializer],
|
|
['props', WitnessUpdatePropertiesSerializer],
|
|
['fee', AssetSerializer]
|
|
]);
|
|
OperationSerializers.witness_set_properties = OperationDataSerializer(33, [
|
|
['owner', StringSerializer],
|
|
['props', FlatMapSerializer(StringSerializer, VariableBinarySerializer)],
|
|
['extensions', ArraySerializer(VoidSerializer)]
|
|
]);
|
|
OperationSerializers.create_proposal = OperationDataSerializer(34, [
|
|
['creator', StringSerializer],
|
|
['receiver', StringSerializer],
|
|
['start_date', DateSerializer],
|
|
['end_date', DateSerializer],
|
|
['daily_pay', AssetSerializer],
|
|
['subject', StringSerializer],
|
|
['permlink', StringSerializer],
|
|
['extensions', ArraySerializer(VoidSerializer)]
|
|
]);
|
|
OperationSerializers.update_proposal_votes = OperationDataSerializer(35, [
|
|
['voter', StringSerializer],
|
|
['proposal_ids', ArraySerializer(Int64Serializer)],
|
|
['approve', BooleanSerializer],
|
|
['extensions', ArraySerializer(VoidSerializer)]
|
|
]);
|
|
OperationSerializers.remove_proposal = OperationDataSerializer(36, [
|
|
['proposal_owner', StringSerializer],
|
|
['proposal_ids', ArraySerializer(Int64Serializer)],
|
|
['extensions', ArraySerializer(VoidSerializer)]
|
|
]);
|
|
OperationSerializers.request_account_recovery = OperationDataSerializer(17, [
|
|
['recovery_account', StringSerializer],
|
|
['account_to_recover', StringSerializer],
|
|
['new_owner_authority', AuthoritySerializer],
|
|
['extensions', ArraySerializer(VoidSerializer)]
|
|
]);
|
|
OperationSerializers.recover_account = OperationDataSerializer(18, [
|
|
['account_to_recover', StringSerializer],
|
|
['new_owner_authority', AuthoritySerializer],
|
|
['recent_owner_authority', AuthoritySerializer],
|
|
['extensions', ArraySerializer(VoidSerializer)]
|
|
]);
|
|
/**
|
|
* END | Operation Serializers
|
|
*/
|
|
const OperationSerializer = (buffer, operation) => {
|
|
const serializer = OperationSerializers[operation[0]];
|
|
if (!serializer) {
|
|
throw new Error(`No serializer for operation: ${operation[0]}`);
|
|
}
|
|
try {
|
|
serializer(buffer, operation[1]);
|
|
}
|
|
catch (error) {
|
|
error.message = `${operation[0]}: ${error.message}`;
|
|
throw error;
|
|
}
|
|
};
|
|
const TransactionSerializer = ObjectSerializer([
|
|
['ref_block_num', UInt16Serializer],
|
|
['ref_block_prefix', UInt32Serializer],
|
|
['expiration', DateSerializer],
|
|
['operations', ArraySerializer(OperationSerializer)],
|
|
['extensions', ArraySerializer(StringSerializer)]
|
|
]);
|
|
exports.Types = {
|
|
Array: ArraySerializer,
|
|
Asset: AssetSerializer,
|
|
Authority: AuthoritySerializer,
|
|
Binary: BinarySerializer,
|
|
Boolean: BooleanSerializer,
|
|
Date: DateSerializer,
|
|
FlatMap: FlatMapSerializer,
|
|
Int16: Int16Serializer,
|
|
Int32: Int32Serializer,
|
|
Int64: Int64Serializer,
|
|
Int8: Int8Serializer,
|
|
Memo: EncryptedMemoSerializer,
|
|
Object: ObjectSerializer,
|
|
Operation: OperationSerializer,
|
|
Optional: OptionalSerializer,
|
|
PublicKey: PublicKeySerializer,
|
|
StaticVariant: StaticVariantSerializer,
|
|
String: StringSerializer,
|
|
Transaction: TransactionSerializer,
|
|
UInt16: UInt16Serializer,
|
|
UInt32: UInt32Serializer,
|
|
UInt64: UInt64Serializer,
|
|
UInt8: UInt8Serializer,
|
|
Void: VoidSerializer
|
|
};
|