AccountIndex encoding updates via util/keyring (#281)
* AccountIndex encoding updates via util/keyring * Proper ss58 AccountIndex decoding from keyring * Metadata allows both length and non-length prefixed * Update doc logo size & relative URL
This commit is contained in:
@@ -30,7 +30,7 @@
|
||||
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/types#readme",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.0.0",
|
||||
"@polkadot/keyring": "^0.31.1",
|
||||
"@polkadot/util": "^0.31.1"
|
||||
"@polkadot/keyring": "^0.31.3",
|
||||
"@polkadot/util": "^0.31.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,12 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import decodeAddress from '@polkadot/keyring/address/decode';
|
||||
import encodeAddress from '@polkadot/keyring/address/encode';
|
||||
import hexToU8a from '@polkadot/util/hex/toU8a';
|
||||
import isU8a from '@polkadot/util/is/u8a';
|
||||
import u8aToHex from '@polkadot/util/u8a/toHex';
|
||||
import u8aToU8a from '@polkadot/util/u8a/toU8a';
|
||||
import isHex from '@polkadot/util/is/hex';
|
||||
import u8aConcat from '@polkadot/util/u8a/concat';
|
||||
|
||||
import { AnyU8a } from './types';
|
||||
import U8a from './codec/U8a';
|
||||
@@ -19,41 +22,53 @@ export default class AccountIndex extends U8a {
|
||||
);
|
||||
}
|
||||
|
||||
// FIXME Not 100% sure how to handle the encoding of short addresses. It is (mostly)
|
||||
// unused atm, options are to go to hex or to utf8. Here we go the hex route.
|
||||
static encode (value: Uint8Array): string {
|
||||
return u8aToHex(value);
|
||||
}
|
||||
|
||||
static decodeAccountIndex (value: AnyU8a): Uint8Array {
|
||||
if (value instanceof U8a) {
|
||||
return value.raw;
|
||||
} else if (Array.isArray(value)) {
|
||||
return AccountIndex.decodeAccountIndex(Uint8Array.from(value));
|
||||
} else if (isU8a(value)) {
|
||||
if (!value.length) {
|
||||
return value;
|
||||
}
|
||||
return value.subarray(0, AccountIndex.readLength(value));
|
||||
|
||||
const [offset, length] = AccountIndex.readLength(value);
|
||||
|
||||
return value.subarray(offset, offset + length);
|
||||
} else if (isHex(value)) {
|
||||
return hexToU8a(value);
|
||||
}
|
||||
return u8aToU8a(value);
|
||||
|
||||
return decodeAddress(value);
|
||||
}
|
||||
|
||||
// TODO Double check the +1 with actual e2e data
|
||||
static readLength (input: Uint8Array): number {
|
||||
static readLength (input: Uint8Array): [number, number] {
|
||||
const first = input[0];
|
||||
|
||||
if (first <= 0xef) {
|
||||
return 1;
|
||||
return [0, 1];
|
||||
} else if (first === 0xfc) {
|
||||
return 2 + 1;
|
||||
return [1, 2];
|
||||
} else if (first === 0xfd) {
|
||||
return 4 + 1;
|
||||
return [1, 4];
|
||||
} else if (first === 0xfe) {
|
||||
return 8 + 1;
|
||||
return [1, 8];
|
||||
}
|
||||
|
||||
throw new Error(`Invalid account index byte, 0x${first.toString(16)}`);
|
||||
}
|
||||
|
||||
static writeLength (input: Uint8Array): Uint8Array {
|
||||
switch (input.length) {
|
||||
case 1: return new Uint8Array([]);
|
||||
case 2: return new Uint8Array([0xfc]);
|
||||
case 4: return new Uint8Array([0xfd]);
|
||||
case 8: return new Uint8Array([0xfe]);
|
||||
}
|
||||
|
||||
throw new Error(`Invalid account index length, ${input.length}`);
|
||||
}
|
||||
|
||||
fromJSON (input: any): AccountIndex {
|
||||
super.fromJSON(AccountIndex.decodeAccountIndex(input));
|
||||
|
||||
@@ -61,9 +76,9 @@ export default class AccountIndex extends U8a {
|
||||
}
|
||||
|
||||
fromU8a (input: Uint8Array): AccountIndex {
|
||||
super.fromU8a(
|
||||
input.subarray(0, AccountIndex.readLength(input))
|
||||
);
|
||||
const [offset, length] = AccountIndex.readLength(input);
|
||||
|
||||
super.fromU8a(input.subarray(offset, offset + length));
|
||||
|
||||
return this;
|
||||
}
|
||||
@@ -72,7 +87,16 @@ export default class AccountIndex extends U8a {
|
||||
return this.toString();
|
||||
}
|
||||
|
||||
toU8a (isBare?: boolean): Uint8Array {
|
||||
return isBare
|
||||
? this.raw
|
||||
: u8aConcat(
|
||||
AccountIndex.writeLength(this.raw),
|
||||
this.raw
|
||||
);
|
||||
}
|
||||
|
||||
toString (): string {
|
||||
return AccountIndex.encode(this.raw);
|
||||
return encodeAddress(this.raw);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,8 +31,8 @@ describe('Address', () => {
|
||||
);
|
||||
testDecode(
|
||||
'AccountIndex',
|
||||
new AccountIndex('0x0102030405060708010203040506070801020304050607080102030405060708'),
|
||||
'0x0102030405060708010203040506070801020304050607080102030405060708'
|
||||
new AccountIndex('0x0001'),
|
||||
'25GUyk'
|
||||
);
|
||||
testDecode(
|
||||
'Array',
|
||||
@@ -54,23 +54,23 @@ describe('Address', () => {
|
||||
);
|
||||
testDecode(
|
||||
'Uint8Array (with prefix 1 byte)',
|
||||
Uint8Array.from([17]),
|
||||
'0x11'
|
||||
Uint8Array.from([1]),
|
||||
'F7L6'
|
||||
);
|
||||
testDecode(
|
||||
'Uint8Array (with prefix 2 bytes)',
|
||||
Uint8Array.from([0xfc, 17, 18]),
|
||||
'0xfc1112'
|
||||
Uint8Array.from([0xfc, 0, 1]),
|
||||
'25GUyk'
|
||||
);
|
||||
testDecode(
|
||||
'Uint8Array (with prefix 4 bytes)',
|
||||
Uint8Array.from([0xfd, 17, 18, 19, 20]),
|
||||
'0xfd11121314'
|
||||
'Mwz15xN8'
|
||||
);
|
||||
testDecode(
|
||||
'Uint8Array (with prefix 8 bytes)',
|
||||
Uint8Array.from([0xfe, 17, 18, 19, 20, 21, 22, 23, 24]),
|
||||
'0xfe1112131415161718'
|
||||
'3N5RJXxM5fLd4h'
|
||||
);
|
||||
|
||||
// FIXME Add this
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import hexToU8a from '@polkadot/util/hex/toU8a';
|
||||
|
||||
import Metadata from './Metadata';
|
||||
import rpcdata from './Metadata.rpc';
|
||||
|
||||
@@ -13,6 +15,13 @@ describe('Metadata', () => {
|
||||
console.error(str);
|
||||
console.error(decoded.getUniqTypes());
|
||||
|
||||
expect(str).not.toBe(null);
|
||||
expect(decoded.events.length).not.toBe(0);
|
||||
});
|
||||
|
||||
it('decodes when length not present (HACK)', () => {
|
||||
const u8a = hexToU8a(rpcdata);
|
||||
const decoded = new Metadata().fromU8a(u8a.subarray(2));
|
||||
|
||||
expect(decoded.events.length).not.toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -336,10 +336,18 @@ export default class RuntimeMetadata extends Struct {
|
||||
}
|
||||
|
||||
fromU8a (input: Uint8Array): RuntimeMetadata {
|
||||
// this does not look correct, metadata now has a length prefix. Strip, move on.
|
||||
const [offset] = Compact.decodeU8a(input, DEFAULT_LENGTH_BITS);
|
||||
// HACK 13 Oct 2018 - For current running BBQ nodes, Metadata is not properly
|
||||
// encoded, it does not have a length prefix. For latest substrate master, it
|
||||
// is properly encoded. Here we pull the prefix, check it agianst the length -
|
||||
// if matches, then we have the length, otherwise we assume it is an older node
|
||||
// and use the whole buffer
|
||||
const [offset, length] = Compact.decodeU8a(input, DEFAULT_LENGTH_BITS);
|
||||
|
||||
super.fromU8a(input.subarray(offset));
|
||||
super.fromU8a(
|
||||
input.length === (offset + length.toNumber())
|
||||
? input.subarray(offset)
|
||||
: input
|
||||
);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user