Skip to content

Commit

Permalink
[HOTFIX] Add custom logic for eth spv create operation (#177)
Browse files Browse the repository at this point in the history
  • Loading branch information
kosAndret authored Oct 19, 2021
1 parent c349773 commit c70ef7d
Show file tree
Hide file tree
Showing 18 changed files with 399 additions and 109 deletions.
4 changes: 4 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ module.exports = {
"plugins": [
"import"
],
"parserOptions": {
"ecmaVersion": 2020,
},
"ignorePatterns": [".eslintrc.js"],
"rules": {
"arrow-parens": [
"error",
Expand Down
6 changes: 3 additions & 3 deletions .test/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ version: "2"

services:
echo:
image: echoprotocol/echo:0.22-rc.1
image: echoprotocol/echo:0.25.0-rc.25
command:
--start-echorand
--account-info="[\"1.2.6\", \"5KkYp8qdQBaRmLqLz8WVrGjzkt7E13qVcr7cpdLowgJ1mjRyDx2\"]"
Expand All @@ -24,11 +24,11 @@ services:
container_name: echo

echo-wallet:
image: echoprotocol/echo-wallet:0.22-rc.1
image: echoprotocol/echo-wallet:0.25.0-rc.25
container_name: echo-wallet
command:
-s ws://echo:6311
--chain-id="acd81c215a20e2b3281195362146215c82874d52783fbb4cb35924edd99c716c"
--chain-id="5db725cf9e9d74db2a8c0e838289d0cc56c89a806e9535f60307aeeb7801b074"
--wallet-file="/echo/walletdata/wallet.json"
--history-file="/echo/walletdata/history"
-r 0.0.0.0:6312
Expand Down
16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "echojs-lib",
"version": "1.13.4",
"version": "1.13.5",
"description": "Pure JavaScript ECHO library for node.js",
"main": "./dist/index.js",
"types": "./types/index.d.ts",
Expand Down Expand Up @@ -35,7 +35,7 @@
"@types/crypto-js": "^3.1.43",
"@types/node": "^12.0.10",
"assert": "^1.4.1",
"axios": "^0.19.2",
"axios": "^0.22.0",
"bigi": "^1.4.2",
"bignumber.js": "^8.0.1",
"bs58": "^4.0.1",
Expand All @@ -52,29 +52,29 @@
"immutable": "^3.8.1",
"isomorphic-ws": "^4.0.1",
"js-sha3": "^0.8.0",
"lodash": "^4.17.11",
"ws": "^7.1.1"
"lodash": "^4.17.21",
"ws": "^7.5.5"
},
"devDependencies": {
"@babel/cli": "^7.2.3",
"@babel/cli": "^7.15.7",
"@babel/core": "^7.2.2",
"@babel/node": "^7.5.5",
"@babel/plugin-transform-runtime": "^7.6.0",
"@babel/polyfill": "^7.7.0",
"@babel/preset-env": "^7.3.1",
"@babel/register": "^7.0.0",
"@types/bytebuffer": "^5.0.40",
"audit-ci": "^2.2.0",
"audit-ci": "^4.1.0",
"chai": "^4.2.0",
"chai-spies": "^1.0.0",
"eslint": "^5.16.0",
"eslint": "^7.32.0",
"eslint-config-airbnb": "^16.1.0",
"eslint-plugin-import": "^2.9.0",
"eslint-plugin-jsx-a11y": "^6.1.2",
"eslint-plugin-react": "7.13.0",
"fs-extra": "^7.0.1",
"husky": "^2.7.0",
"mocha": "^7.1.1",
"mocha": "^9.1.2",
"redux": "^4.0.1",
"typescript": "^3.5.3"
}
Expand Down
12 changes: 10 additions & 2 deletions src/serializers/basic/Bytes.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,17 @@ export default class BytesSerializer extends ISerializer {
*/
get bytesCount() { return this._bytesCount; }

/**
* @readonly
* @type {boolean}
*/
get isNeed0xPrefix() { return this._isNeed0xPrefix; }

/** @param {number} [bytesCount] */
constructor(bytesCount) {
/** @param {boolean} [isNeed0xPrefix] */
constructor(bytesCount, isNeed0xPrefix = false) {
super();
this._isNeed0xPrefix = isNeed0xPrefix;
if (bytesCount !== undefined) {
try {
if (bytesCount < 0) throw new Error('bytes serializer size is negative');
Expand All @@ -42,7 +50,7 @@ export default class BytesSerializer extends ISerializer {
value = Buffer.from(value.toLowerCase(), 'hex');
} else if (!Buffer.isBuffer(value)) throw new Error('invalid bytes type');
if (this.bytesCount !== undefined && value.length !== this.bytesCount) throw new Error('invalid bytes count');
return value.toString('hex');
return `${this.isNeed0xPrefix ? '0x' : ''}${value.toString('hex')}`;
}

/**
Expand Down
3 changes: 2 additions & 1 deletion src/serializers/basic/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ export const bool = new BoolSerializer();

/**
* @param {number} bytesCount
* @param {boolean} isNeed0xPrefix
* @returns {BytesSerializer}
*/
export const bytes = (bytesCount) => new BytesSerializer(bytesCount);
export const bytes = (bytesCount, isNeed0xPrefix) => new BytesSerializer(bytesCount, isNeed0xPrefix);

export const string = new StringSerializer();
export const timePointSec = new TimePointSecSerializer();
Expand Down
1 change: 1 addition & 0 deletions src/serializers/chain/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const privateKey = new PrivateKeySerializer();
export const weight = uint16;
export const ripemd160 = bytes(20);
export const sha256 = bytes(32);
export const sha256With0xPrefix = bytes(32, true);
export const checksum = ripemd160;

export { ids, PublicKeySerializer, PrivateKeySerializer };
219 changes: 219 additions & 0 deletions src/serializers/collections/StructWithVariantKeys.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
import ISerializer from '../ISerializer';
import { staticVariant } from '.';

/** @typedef {import("bytebuffer")} ByteBuffer */

/**
* @template {ISerializer} T
* @typedef {import("../ISerializer").SerializerInput<T>} SerializerInput
*/

/**
* @template {ISerializer} T
* @typedef {import("../ISerializer").SerializerOutput<T>} SerializerOutput
*/

/** @typedef {{ [key: string]: ISerializer }} SerializersMap */

/** @typedef {{ [key: string]: ISerializer | ISerializer[] }} SerializersMapWithVariants */

/** @typedef {{
* keyIndexInStructure: number,
* serializersData: [string, ISerializer][],
* }} ExtraSerializer
*/

/** @typedef {ExtraSerializer[]} ExtraSerializers
/** @typedef {ExtraSerializer['serializersData'][number][0]} ExtraSerializerKey
/**
* @template {SerializersMap} T
* @template {ExtraSerializers} V
* @typedef {{
* [key in keyof T]: SerializerInput<T[key]
* & { [key in ExtraSerializerKey]: SerializerInput<V[number]['serializersData'][number][1]>>
* }} TInput
*/

/**
* @template {SerializersMap} T
* @template {ExtraSerializers} V
* @typedef {{
* [key in keyof T]: SerializerOutput<T[key]
* & { [key in ExtraSerializerKey]: SerializerInput<V[number]['serializersData'][number][1]>>
* }} TOutput
*/

/**
* @template {SerializersMap} T
* @template {ExtraSerializers} V
* @augments {ISerializer<TInput<T, V>, TOutput<T, V>>}
*/
export default class StructWithVariantKeysSerializer extends ISerializer {

/**
* @readonly
* @type {Readonly<T>}
*/
get serializers() { return this._serializers; }

/**
* @readonly
* @type {Readonly<V>}
*/
get extraSerializers() { return this._extraSerializers; }

/**
* @param {Readonly<T>} serializers
* @param {Readonly<V>} extraSerializers
*/
constructor(serializers, extraSerializers) {
if (typeof serializers !== 'object' || serializers === null) {
throw new Error('property "serializers" is not a object');
}
for (const key in serializers) {
if (!Object.prototype.hasOwnProperty.call(serializers, key)) continue;
const serializer = serializers[key];
if (!(serializer instanceof ISerializer)) {
throw new Error(`field "${key}" is not a serializer`);
}
}
super();
/**
* @private
* @type {Object<string,Type>}
*/
this._serializers = serializers;
this._extraSerializers = extraSerializers.sort((el1, el2) => el1.keyIndexInStructure - el2.keyIndexInStructure);
}

/**
* @param {TInput<T, V>} value
* @param {[string, ISerializer][]} serializersData
* @returns {[string, number]}
*/
findSerializerKeyInVariant(value, serializersData) {
let variantKey;
let index;
for (let i = 0; i < serializersData.length; i += 1) {
const currentKey = serializersData[i][0];
if (value[currentKey]) {
variantKey = currentKey;
index = i;
break;
}
}
return [variantKey, index];
}

/**
* @param {TInput<T, V>} value
* @returns {TOutput<T, V>}
*/
toRaw(value) {
if (typeof value !== 'object' || value === null) throw new Error('serializable struct is not a object');
/** @type {TOutput<T>} */
const result = {};
let iterator = 0;
const serializersKeys = Object.keys(this.serializers);
for (let i = 0; i < serializersKeys.length + this.extraSerializers.length; i += 1) {
// eslint-disable-next-line no-loop-func
const variantKeySerializer = this.extraSerializers.find((el) => el.keyIndexInStructure === iterator);
if (variantKeySerializer) {
const { serializersData } = variantKeySerializer;
const [variantKey, index] = this.findSerializerKeyInVariant(value, serializersData);
const [rawKey, rawValue] = staticVariant(variantKeySerializer.serializersData.map((el) => el[1]))
.toRaw([index, value[variantKey]]);
const resultKey = variantKeySerializer.serializersData[rawKey][0];
result[resultKey] = rawValue;
iterator += 1;
}

if (i >= serializersKeys.length) {
iterator += 1;
continue;
}
const key = serializersKeys[i];
if (!Object.prototype.hasOwnProperty.call(this.serializers, key)) continue;
const serializer = this.serializers[key];
try {
result[key] = serializer.toRaw(value[key]);
} catch (error) {
throw new Error(`struct key "${key}": ${error.message}`);
}
iterator += 1;
}
return result;
}

/**
* @param {TInput<T, V>} value
* @param {ByteBuffer} bytebuffer
*/
appendToByteBuffer(value, bytebuffer) {
const raw = this.toRaw(value);
let iterator = 0;
const serializersKeys = Object.keys(this.serializers);
for (let i = 0; i < serializersKeys.length + this.extraSerializers.length; i += 1) {
// eslint-disable-next-line no-loop-func
const variantKeySerializer = this.extraSerializers.find((el) => el.keyIndexInStructure === iterator);
if (variantKeySerializer) {
const { serializersData } = variantKeySerializer;
const [variantKey, index] = this.findSerializerKeyInVariant(value, serializersData);
staticVariant(variantKeySerializer.serializersData.map((el) => el[1]))
.appendToByteBuffer([index, value[variantKey]], bytebuffer);
iterator += 1;
}

if (i >= serializersKeys.length) {
iterator += 1;
continue;
}
const key = serializersKeys[i];
if (!Object.prototype.hasOwnProperty.call(this.serializers, key)) continue;
const serializer = this.tserializers[key];
serializer.appendToByteBuffer(raw[key], bytebuffer);
iterator += 1;
}
}

/**
* @param {Buffer} buffer
* @param {number} [offset]
* @returns {{ res: TOutput<T, V>, newOffset: number }}
*/
readFromBuffer(buffer, offset = 0) {
const result = {};
let it = offset;
let iterator = 0;
const serializersKeys = Object.keys(this.serializers);
for (let i = 0; i < serializersKeys.length + this.extraSerializers.length; i += 1) {

// eslint-disable-next-line no-loop-func
const variantKeySerializer = this.extraSerializers.find((el) => el.keyIndexInStructure === iterator);
if (variantKeySerializer) {
const { res, newOffset } = staticVariant(variantKeySerializer.serializersData.map((el) => el[1]))
.readFromBuffer(buffer, it);
it = newOffset;
const [rawKey, variant] = res;
const resultKey = variantKeySerializer.serializersData[rawKey][0];
result[resultKey] = variant;
iterator += 1;
}
if (i >= serializersKeys.length) {
iterator += 1;
continue;
}
const key = serializersKeys[i];
const serializer = this.serializers[key];
if (!Object.prototype.hasOwnProperty.call(this.serializers, key)) continue;
const { res: element, newOffset } = serializer.readFromBuffer(buffer, it);
it = newOffset;
result[key] = element;
iterator += 1;
}
return { res: result, newOffset: it };
}

}
14 changes: 14 additions & 0 deletions src/serializers/collections/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import StaticVariantSerializer from './StaticVariant';
import StructSerializer from './Struct';
import VectorSerializer from './Vector';
import PairSerializer from './Pair';
import StructWithVariantKeysSerializer from './StructWithVariantKeys';

/** @typedef {import("../ISerializer").default} ISerializer */

Expand Down Expand Up @@ -57,6 +58,19 @@ export const staticVariant = (serializers) => new StaticVariantSerializer(serial
*/
export const struct = (serializers) => new StructSerializer(serializers);

/**
* @template {SerializersMap} T
* @template { {
* keyIndexInStructure: number,
* serializersData: [string, ISerializer][],
* }[] } V
* @param {T} serializers
* @param {V} extraSerializers
* @returns {StructWithVariantKeysSerializer<T, V>}
*/
export const structWithVariantKeys = (serializers, extraSerializers) =>
new StructWithVariantKeysSerializer(serializers, extraSerializers);

/**
* @template {ISerializer} T
* @param {T} serializer
Expand Down
Loading

0 comments on commit c70ef7d

Please sign in to comment.