@greymass/eosio
Advanced tools
Comparing version 0.4.9 to 0.5.0
{ | ||
"name": "@greymass/eosio", | ||
"description": "Library for working with EOSIO blockchains", | ||
"version": "0.4.9", | ||
"version": "0.5.0", | ||
"homepage": "https://github.com/greymass/eosio-core", | ||
@@ -6,0 +6,0 @@ "license": "BSD-3-Clause", |
@@ -1,2 +0,2 @@ | ||
import {APIProvider, FetchProvider, FetchProviderOptions} from './provider' | ||
import {APIProvider, APIResponse, FetchProvider, FetchProviderOptions} from './provider' | ||
import {ABISerializableConstructor, ABISerializableType} from '../serializer/serializable' | ||
@@ -33,3 +33,10 @@ import {abiDecode} from '../serializer/decoder' | ||
static formatError(error: APIErrorData) { | ||
if (error.what === 'unspecified' && error.details && error.details.length > 0) { | ||
if ( | ||
error.what === 'unspecified' && | ||
error.details[0]?.file === 'http_plugin.cpp' && | ||
error.details[0].message.slice(0, 11) === 'unknown key' | ||
) { | ||
// fix cryptic error messages from nodeos for missing accounts | ||
return 'Account not found' | ||
} else if (error.what === 'unspecified' && error.details && error.details.length > 0) { | ||
return error.details[0].message | ||
@@ -43,9 +50,28 @@ } else if (error.what && error.what.length > 0) { | ||
constructor(public readonly path: string, public readonly error: APIErrorData) { | ||
super(`${APIError.formatError(error)} at ${path}`) | ||
/** The path to the API that failed, e.g. `/v1/chain/get_info`. */ | ||
readonly path: string | ||
/** The full response from the API that failed. */ | ||
readonly response: APIResponse | ||
constructor(path: string, response: APIResponse) { | ||
let message: string | ||
if (response.json && response.json.error) { | ||
message = `${APIError.formatError(response.json.error)} at ${path}` | ||
} else { | ||
message = `HTTP ${response.status} at ${path}` | ||
} | ||
super(message) | ||
this.path = path | ||
this.response = response | ||
} | ||
/** The nodeos error object. */ | ||
get error() { | ||
return this.response.json?.error as APIErrorData | undefined | ||
} | ||
/** The nodeos error name, e.g. `tx_net_usage_exceeded` */ | ||
get name() { | ||
return this.error.name || 'unspecified' | ||
return this.error?.name || 'unspecified' | ||
} | ||
@@ -55,3 +81,3 @@ | ||
get code() { | ||
return this.error.code || 0 | ||
return this.error?.code || 0 | ||
} | ||
@@ -61,3 +87,3 @@ | ||
get details() { | ||
return this.error.details | ||
return this.error?.details || [] | ||
} | ||
@@ -98,11 +124,11 @@ } | ||
async call(args: {path: string; params?: unknown; responseType?: ABISerializableType}) { | ||
const response = (await this.provider.call(args.path, args.params)) as any | ||
if (response.error) { | ||
throw new APIError(args.path, response.error) | ||
const response = await this.provider.call(args.path, args.params) | ||
if (Math.floor(response.status / 100) !== 2 || typeof response.json?.error === 'object') { | ||
throw new APIError(args.path, response) | ||
} | ||
if (args.responseType) { | ||
return abiDecode({type: args.responseType, object: response}) | ||
return abiDecode({type: args.responseType, object: response.json}) | ||
} | ||
return response | ||
return response.json || response.text | ||
} | ||
} |
type Fetch = (input: any, init?: any) => Promise<any> | ||
/** Response to an API call. */ | ||
export interface APIResponse { | ||
json?: any | ||
text: string | ||
status: number | ||
headers: Record<string, string> | ||
} | ||
export interface APIProvider { | ||
@@ -10,3 +18,3 @@ /** | ||
*/ | ||
call(path: string, params?: unknown): Promise<unknown> | ||
call(path: string, params?: unknown): Promise<APIResponse> | ||
} | ||
@@ -50,12 +58,15 @@ | ||
}) | ||
const text = await response.text() | ||
let json: any | ||
try { | ||
return response.json() | ||
} catch (error) { | ||
if (!response.ok) { | ||
throw Error(`HTTP ${response.status}: ${response.statusText}`) | ||
} | ||
error.message = `Unable to parse JSON response from server: ${error.message}` | ||
throw error | ||
json = JSON.parse(text) | ||
} catch { | ||
// ignore json parse errors | ||
} | ||
const headers = {} | ||
for (const [key, value] of response.headers.entries()) { | ||
headers[key] = value | ||
} | ||
return {headers, status: response.status, json, text} | ||
} | ||
} |
@@ -6,4 +6,7 @@ import {ABISerializableObject} from '../serializer/serializable' | ||
export type BytesType = Bytes | Uint8Array | ArrayLike<number> | string | ||
export type BytesType = Bytes | ArrayBufferView | ArrayBuffer | ArrayLike<number> | string | ||
// This allows passing any object following the .array convention to a Bytes method | ||
type AnyBytes = BytesType | {array: Uint8Array} | ||
export type BytesEncoding = 'hex' | 'utf8' | ||
@@ -14,3 +17,7 @@ | ||
static from(value: BytesType, encoding?: BytesEncoding): Bytes { | ||
/** | ||
* Create a new Bytes instance. | ||
* @note Make sure to take a [[copy]] before mutating the bytes as the underlying source is not copied here. | ||
*/ | ||
static from(value: AnyBytes, encoding?: BytesEncoding): Bytes { | ||
if (isInstanceOf(value, this)) { | ||
@@ -22,6 +29,9 @@ return value | ||
} | ||
if (isInstanceOf(value, Uint8Array)) { | ||
return new this(value) | ||
if (ArrayBuffer.isView(value)) { | ||
return new this(new Uint8Array(value.buffer, value.byteOffset, value.byteLength)) | ||
} | ||
return new this(new Uint8Array(value)) | ||
if (isInstanceOf(value['array'], Uint8Array)) { | ||
return new this(value['array']) | ||
} | ||
return new this(new Uint8Array(value as any)) | ||
} | ||
@@ -82,3 +92,4 @@ | ||
appending(other: BytesType): Bytes { | ||
/** Mutating. Append bytes to this instance. */ | ||
append(other: AnyBytes) { | ||
other = Bytes.from(other) | ||
@@ -90,5 +101,12 @@ const newSize = this.array.byteLength + other.array.byteLength | ||
array.set(other.array, this.array.byteLength) | ||
return new Bytes(array) | ||
this.array = array | ||
} | ||
/** Non-mutating, returns a copy of this instance with appended bytes. */ | ||
appending(other: AnyBytes): Bytes { | ||
const rv = new Bytes(this.array) | ||
rv.append(other) | ||
return rv | ||
} | ||
droppingFirst(n = 1) { | ||
@@ -105,3 +123,3 @@ return new Bytes(this.array.subarray(n)) | ||
equals(other: BytesType): boolean { | ||
equals(other: AnyBytes): boolean { | ||
return arrayEquals(this.array, Bytes.from(other).array) | ||
@@ -108,0 +126,0 @@ } |
// types with no inter-dependencies | ||
export * from './bytes' | ||
export * from './checksum' | ||
export * from './curve-type' | ||
export * from './key-type' | ||
export * from './integer' | ||
@@ -6,0 +6,0 @@ export * from './struct' |
@@ -15,3 +15,3 @@ import {Base58} from '../base58' | ||
Checksum512, | ||
CurveType, | ||
KeyType, | ||
PublicKey, | ||
@@ -24,3 +24,3 @@ Signature, | ||
export class PrivateKey { | ||
type: CurveType | ||
type: KeyType | ||
data: Bytes | ||
@@ -45,3 +45,3 @@ | ||
return new this(type, data) | ||
} catch (error) { | ||
} catch (error: any) { | ||
error.message = `Invalid private key (${error.message})` | ||
@@ -53,3 +53,3 @@ if ( | ||
) { | ||
const type = string.startsWith('PVT_R1') ? CurveType.R1 : CurveType.K1 | ||
const type = string.startsWith('PVT_R1') ? KeyType.R1 : KeyType.K1 | ||
let data = new Bytes(error.info.data) | ||
@@ -69,8 +69,8 @@ if (data.array.length == 33) { | ||
*/ | ||
static generate(type: CurveType | string) { | ||
return new PrivateKey(CurveType.from(type), new Bytes(generate(type))) | ||
static generate(type: KeyType | string) { | ||
return new PrivateKey(KeyType.from(type), new Bytes(generate(type))) | ||
} | ||
/** @internal */ | ||
constructor(type: CurveType, data: Bytes) { | ||
constructor(type: KeyType, data: Bytes) { | ||
this.type = type | ||
@@ -120,3 +120,3 @@ this.data = data | ||
toWif() { | ||
if (this.type !== CurveType.K1) { | ||
if (this.type !== KeyType.K1) { | ||
throw new Error('Unable to generate WIF for non-k1 key') | ||
@@ -151,7 +151,7 @@ } | ||
} | ||
const type = CurveType.from(parts[1]) | ||
const type = KeyType.from(parts[1]) | ||
let size: number | undefined | ||
switch (type) { | ||
case CurveType.K1: | ||
case CurveType.R1: | ||
case KeyType.K1: | ||
case KeyType.R1: | ||
size = 32 | ||
@@ -164,3 +164,3 @@ break | ||
// WIF format | ||
const type = CurveType.K1 | ||
const type = KeyType.K1 | ||
const data = Base58.decodeCheck(value) | ||
@@ -167,0 +167,0 @@ if (data.array[0] !== 0x80) { |
@@ -8,3 +8,3 @@ import {ABIDecoder} from '../serializer/decoder' | ||
import {Bytes, CurveType} from '../' | ||
import {Bytes, KeyType} from '../' | ||
@@ -17,3 +17,3 @@ export type PublicKeyType = PublicKey | string | {type: string; compressed: Uint8Array} | ||
/** Type, e.g. `K1` */ | ||
type: CurveType | ||
type: KeyType | ||
/** Compressed public key point. */ | ||
@@ -28,3 +28,3 @@ data: Bytes | ||
if (typeof value === 'object' && value.type && value.compressed) { | ||
return new PublicKey(CurveType.from(value.type), new Bytes(value.compressed)) | ||
return new PublicKey(KeyType.from(value.type), new Bytes(value.compressed)) | ||
} | ||
@@ -39,4 +39,4 @@ if (typeof value !== 'string') { | ||
} | ||
const type = CurveType.from(parts[1]) | ||
const size = type === CurveType.K1 || type === CurveType.R1 ? 33 : undefined | ||
const type = KeyType.from(parts[1]) | ||
const size = type === KeyType.K1 || type === KeyType.R1 ? 33 : undefined | ||
const data = Base58.decodeRipemd160Check(parts[2], size, type) | ||
@@ -47,3 +47,3 @@ return new PublicKey(type, data) | ||
const data = Base58.decodeRipemd160Check(value.slice(-50)) | ||
return new PublicKey(CurveType.K1, data) | ||
return new PublicKey(KeyType.K1, data) | ||
} else { | ||
@@ -56,9 +56,12 @@ throw new Error('Invalid public key string') | ||
static fromABI(decoder: ABIDecoder) { | ||
const type = CurveType.from(decoder.readByte()) | ||
if (type == CurveType.WA) { | ||
// "WA" keys pack some sort of metadata | ||
// we probably need to restructure key data storage into containers like FC does | ||
const data = new Bytes(decoder.readArray(33)) | ||
Bytes.fromABI(decoder) // throw away metadata for now | ||
return new PublicKey(type, data) | ||
const type = KeyType.from(decoder.readByte()) | ||
if (type == KeyType.WA) { | ||
const startPos = decoder.getPosition() | ||
decoder.advance(33) // key_data | ||
decoder.advance(1) // user presence | ||
decoder.advance(decoder.readVaruint32()) // rpid | ||
const len = decoder.getPosition() - startPos | ||
decoder.setPosition(startPos) | ||
const data = Bytes.from(decoder.readArray(len)) | ||
return new PublicKey(KeyType.WA, data) | ||
} | ||
@@ -69,3 +72,3 @@ return new PublicKey(type, new Bytes(decoder.readArray(33))) | ||
/** @internal */ | ||
constructor(type: CurveType, data: Bytes) { | ||
constructor(type: KeyType, data: Bytes) { | ||
this.type = type | ||
@@ -85,3 +88,3 @@ this.data = data | ||
toLegacyString(prefix = 'EOS') { | ||
if (this.type !== CurveType.K1) { | ||
if (this.type !== KeyType.K1) { | ||
throw new Error('Unable to create legacy formatted string for non-K1 key') | ||
@@ -99,6 +102,3 @@ } | ||
toABI(encoder: ABIEncoder) { | ||
if (this.type === CurveType.WA) { | ||
throw new Error('WA keys are not supported yet') | ||
} | ||
encoder.writeByte(CurveType.indexFor(this.type)) | ||
encoder.writeByte(KeyType.indexFor(this.type)) | ||
encoder.writeArray(this.data.array) | ||
@@ -105,0 +105,0 @@ } |
@@ -11,3 +11,3 @@ import {ABIDecoder} from '../serializer/decoder' | ||
import {Bytes, BytesType, Checksum256, Checksum256Type, CurveType, PublicKey} from '../' | ||
import {Bytes, BytesType, Checksum256, Checksum256Type, KeyType, PublicKey} from '../' | ||
@@ -23,3 +23,3 @@ export type SignatureType = | ||
/** Type, e.g. `K1` */ | ||
type: CurveType | ||
type: KeyType | ||
/** Signature data. */ | ||
@@ -36,4 +36,4 @@ data: Bytes | ||
let recid = value.recid | ||
const type = CurveType.from(value.type) | ||
if (value.type === CurveType.K1 || value.type === CurveType.R1) { | ||
const type = KeyType.from(value.type) | ||
if (value.type === KeyType.K1 || value.type === KeyType.R1) { | ||
recid += 31 | ||
@@ -54,4 +54,4 @@ } | ||
} | ||
const type = CurveType.from(parts[1]) | ||
const size = type === CurveType.K1 || type === CurveType.R1 ? 65 : undefined | ||
const type = KeyType.from(parts[1]) | ||
const size = type === KeyType.K1 || type === KeyType.R1 ? 65 : undefined | ||
const data = Base58.decodeRipemd160Check(parts[2], size, type) | ||
@@ -66,9 +66,12 @@ return new Signature(type, data) | ||
static fromABI(decoder: ABIDecoder) { | ||
const type = CurveType.from(decoder.readByte()) | ||
if (type === CurveType.WA) { | ||
// same as with public keys WA type has some extra data tacked on | ||
const data = new Bytes(decoder.readArray(65)) // sig | ||
Bytes.fromABI(decoder) // throw away for now | ||
Bytes.fromABI(decoder) | ||
return new Signature(CurveType.WA, data) | ||
const type = KeyType.from(decoder.readByte()) | ||
if (type === KeyType.WA) { | ||
const startPos = decoder.getPosition() | ||
decoder.advance(65) // compact_signature | ||
decoder.advance(decoder.readVaruint32()) // auth_data | ||
decoder.advance(decoder.readVaruint32()) // client_json | ||
const len = decoder.getPosition() - startPos | ||
decoder.setPosition(startPos) | ||
const data = Bytes.from(decoder.readArray(len)) | ||
return new Signature(KeyType.WA, data) | ||
} | ||
@@ -79,3 +82,3 @@ return new Signature(type, new Bytes(decoder.readArray(65))) | ||
/** @internal */ | ||
constructor(type: CurveType, data: Bytes) { | ||
constructor(type: KeyType, data: Bytes) { | ||
this.type = type | ||
@@ -120,6 +123,3 @@ this.data = data | ||
toABI(encoder: ABIEncoder) { | ||
if (this.type === CurveType.WA) { | ||
throw new Error('WA signatures are not supported yet') | ||
} | ||
encoder.writeByte(CurveType.indexFor(this.type)) | ||
encoder.writeByte(KeyType.indexFor(this.type)) | ||
encoder.writeArray(this.data.array) | ||
@@ -126,0 +126,0 @@ } |
@@ -332,2 +332,18 @@ /** | ||
setPosition(pos: number) { | ||
if (pos < 0 || pos > this.array.byteLength) { | ||
throw new Error('Invalid position') | ||
} | ||
this.pos = pos | ||
} | ||
getPosition(): number { | ||
return this.pos | ||
} | ||
advance(bytes: number) { | ||
this.ensure(bytes) | ||
this.pos += bytes | ||
} | ||
/** Read one byte. */ | ||
@@ -334,0 +350,0 @@ readByte(): number { |
@@ -334,2 +334,6 @@ /** | ||
} | ||
getBytes(): Bytes { | ||
return new Bytes(this.getData()) | ||
} | ||
} |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
809502
16162