parent
983d1bffab
commit
1783c54b08
@ -0,0 +1,159 @@ |
|||||||
|
// this file is ported from https://github.com/ethers-io/ethers.js/blob/master/src.ts/utils/rlp.ts
|
||||||
|
// and done some fixes
|
||||||
|
import { arrayify, hexlify, Arrayish } from './bytes'; |
||||||
|
|
||||||
|
function arrayifyInteger(value: number): number[] { |
||||||
|
const result = []; |
||||||
|
while (value) { |
||||||
|
result.unshift(value & 0xff); |
||||||
|
value >>= 8; |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
function unarrayifyInteger( |
||||||
|
data: Uint8Array, |
||||||
|
offset: number, |
||||||
|
length: number, |
||||||
|
): number { |
||||||
|
let result = 0; |
||||||
|
for (let i = 0; i < length; i++) { |
||||||
|
result = result * 256 + data[offset + i]; |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
function _encode(object: any[] | string): number[] { |
||||||
|
if (Array.isArray(object)) { |
||||||
|
let payload: number[] = []; |
||||||
|
object.forEach((child) => { |
||||||
|
payload = payload.concat(_encode(child)); |
||||||
|
}); |
||||||
|
|
||||||
|
if (payload.length <= 55) { |
||||||
|
payload.unshift(0xc0 + payload.length); |
||||||
|
return payload; |
||||||
|
} |
||||||
|
|
||||||
|
// tslint:disable-next-line: no-shadowed-variable
|
||||||
|
const length = arrayifyInteger(payload.length); |
||||||
|
length.unshift(0xf7 + length.length); |
||||||
|
|
||||||
|
return length.concat(payload); |
||||||
|
} |
||||||
|
|
||||||
|
const data: number[] = Array.prototype.slice.call(arrayify(object)); |
||||||
|
|
||||||
|
if (data.length === 1 && data[0] <= 0x7f) { |
||||||
|
return data; |
||||||
|
} else if (data.length <= 55) { |
||||||
|
data.unshift(0x80 + data.length); |
||||||
|
return data; |
||||||
|
} |
||||||
|
|
||||||
|
const length = arrayifyInteger(data.length); |
||||||
|
length.unshift(0xb7 + length.length); |
||||||
|
|
||||||
|
return length.concat(data); |
||||||
|
} |
||||||
|
|
||||||
|
export function encode(object: any): string { |
||||||
|
return hexlify(_encode(object)); |
||||||
|
} |
||||||
|
|
||||||
|
interface Decoded { |
||||||
|
result: any; |
||||||
|
consumed: number; |
||||||
|
} |
||||||
|
|
||||||
|
function _decodeChildren( |
||||||
|
data: Uint8Array, |
||||||
|
offset: number, |
||||||
|
childOffset: number, |
||||||
|
length: number, |
||||||
|
): Decoded { |
||||||
|
const result = []; |
||||||
|
|
||||||
|
while (childOffset < offset + 1 + length) { |
||||||
|
const decoded = _decode(data, childOffset); |
||||||
|
|
||||||
|
result.push(decoded.result); |
||||||
|
|
||||||
|
childOffset += decoded.consumed; |
||||||
|
if (childOffset > offset + 1 + length) { |
||||||
|
throw new Error('invalid rlp'); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return { consumed: 1 + length, result }; |
||||||
|
} |
||||||
|
|
||||||
|
// returns { consumed: number, result: Object }
|
||||||
|
function _decode( |
||||||
|
data: Uint8Array, |
||||||
|
offset: number, |
||||||
|
): { consumed: number; result: any } { |
||||||
|
if (data.length === 0) { |
||||||
|
throw new Error('invalid rlp data'); |
||||||
|
} |
||||||
|
|
||||||
|
// Array with extra length prefix
|
||||||
|
if (data[offset] >= 0xf8) { |
||||||
|
const lengthLength = data[offset] - 0xf7; |
||||||
|
if (offset + 1 + lengthLength > data.length) { |
||||||
|
throw new Error('too short'); |
||||||
|
} |
||||||
|
|
||||||
|
const length = unarrayifyInteger(data, offset + 1, lengthLength); |
||||||
|
if (offset + 1 + lengthLength + length > data.length) { |
||||||
|
throw new Error('to short'); |
||||||
|
} |
||||||
|
|
||||||
|
return _decodeChildren( |
||||||
|
data, |
||||||
|
offset, |
||||||
|
offset + 1 + lengthLength, |
||||||
|
lengthLength + length, |
||||||
|
); |
||||||
|
} else if (data[offset] >= 0xc0) { |
||||||
|
const length = data[offset] - 0xc0; |
||||||
|
if (offset + 1 + length > data.length) { |
||||||
|
throw new Error('invalid rlp data'); |
||||||
|
} |
||||||
|
|
||||||
|
return _decodeChildren(data, offset, offset + 1, length); |
||||||
|
} else if (data[offset] >= 0xb8) { |
||||||
|
const lengthLength = data[offset] - 0xb7; |
||||||
|
if (offset + 1 + lengthLength > data.length) { |
||||||
|
throw new Error('invalid rlp data'); |
||||||
|
} |
||||||
|
|
||||||
|
const length = unarrayifyInteger(data, offset + 1, lengthLength); |
||||||
|
if (offset + 1 + lengthLength + length > data.length) { |
||||||
|
throw new Error('invalid rlp data'); |
||||||
|
} |
||||||
|
|
||||||
|
const result = hexlify( |
||||||
|
data.slice(offset + 1 + lengthLength, offset + 1 + lengthLength + length), |
||||||
|
); |
||||||
|
return { consumed: 1 + lengthLength + length, result }; |
||||||
|
} else if (data[offset] >= 0x80) { |
||||||
|
const length = data[offset] - 0x80; |
||||||
|
if (offset + 1 + length > data.length) { |
||||||
|
throw new Error('invlaid rlp data'); |
||||||
|
} |
||||||
|
|
||||||
|
const result = hexlify(data.slice(offset + 1, offset + 1 + length)); |
||||||
|
return { consumed: 1 + length, result }; |
||||||
|
} |
||||||
|
return { consumed: 1, result: hexlify(data[offset]) }; |
||||||
|
} |
||||||
|
|
||||||
|
export function decode(data: Arrayish): any { |
||||||
|
const bytes = arrayify(data) || new Uint8Array(); |
||||||
|
const decoded = _decode(bytes, 0); |
||||||
|
if (decoded.consumed !== bytes.length) { |
||||||
|
throw new Error('invalid rlp data'); |
||||||
|
} |
||||||
|
return decoded.result; |
||||||
|
} |
@ -0,0 +1,20 @@ |
|||||||
|
{ |
||||||
|
"name": "@harmony/transaction", |
||||||
|
"version": "0.0.1", |
||||||
|
"description": "transaction package for harmony", |
||||||
|
"main": "dist/index.js", |
||||||
|
"node": "dist/index.js", |
||||||
|
"browser": "dist/index.js", |
||||||
|
"module": "dist/index.esm.js", |
||||||
|
"jsnext:main": "dist/index.esm.js", |
||||||
|
"typings": "dist/index.d.ts", |
||||||
|
"scripts": { |
||||||
|
"test": "echo \"Error: no test specified\" && exit 1" |
||||||
|
}, |
||||||
|
"author": "neeboo@firestack.one", |
||||||
|
"license": "ISC", |
||||||
|
"dependencies": { |
||||||
|
"@harmony/crypto": "^0.0.1", |
||||||
|
"@harmony/utils": "^0.0.1" |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,3 @@ |
|||||||
|
class TransactionFactory {} |
||||||
|
|
||||||
|
export { TransactionFactory }; |
@ -0,0 +1,2 @@ |
|||||||
|
export * from './factory'; |
||||||
|
export * from './transaction'; |
@ -0,0 +1,2 @@ |
|||||||
|
class Transaction {} |
||||||
|
export { Transaction }; |
@ -0,0 +1,12 @@ |
|||||||
|
{ |
||||||
|
"extends": "../../tsconfig.base.json", |
||||||
|
"compilerOptions": { |
||||||
|
"outDir": "dist", |
||||||
|
"rootDir": "src" |
||||||
|
}, |
||||||
|
"include": ["src", "../../typings/**/*.d.ts"], |
||||||
|
"references": [ |
||||||
|
{ "path": "../harmony-utils" }, |
||||||
|
{ "path": "../harmony-crypto" } |
||||||
|
] |
||||||
|
} |
Loading…
Reference in new issue