UNPKG

3.66 kBJavaScriptView Raw
1// Copyright 2017-2022 @polkadot/types authors & contributors
2// SPDX-License-Identifier: Apache-2.0
3import { Base } from '@polkadot/types-codec';
4import { isBigInt, isBn, isHex, isNumber, isU8a, u8aConcat, u8aToBn, u8aToHex, u8aToU8a } from '@polkadot/util';
5import { decodeAddress } from '@polkadot/util-crypto';
6import { GenericAccountIndex } from "../generic/AccountIndex.js";
7import { GenericEthereumAccountId } from "./AccountId.js"; // eslint-disable-next-line no-use-before-define
8
9export const ACCOUNT_ID_PREFIX = new Uint8Array([0xff]);
10/** @internal */
11
12function decodeString(registry, value) {
13 const decoded = decodeAddress(value);
14 return decoded.length === 20 ? registry.createTypeUnsafe('EthereumAccountId', [decoded]) : registry.createTypeUnsafe('AccountIndex', [u8aToBn(decoded, true)]);
15}
16/** @internal */
17
18
19function decodeU8a(registry, value) {
20 // This allows us to instantiate an address with a raw publicKey. Do this first before
21 // we checking the first byte, otherwise we may split an already-existent valid address
22 if (value.length === 20) {
23 return registry.createTypeUnsafe('EthereumAccountId', [value]);
24 } else if (value[0] === 0xff) {
25 return registry.createTypeUnsafe('EthereumAccountId', [value.subarray(1)]);
26 }
27
28 const [offset, length] = GenericAccountIndex.readLength(value);
29 return registry.createTypeUnsafe('AccountIndex', [u8aToBn(value.subarray(offset, offset + length), true)]);
30}
31
32function decodeAddressOrIndex(registry, value) {
33 return value instanceof GenericEthereumLookupSource ? value.inner : value instanceof GenericEthereumAccountId || value instanceof GenericAccountIndex ? value : isU8a(value) || Array.isArray(value) || isHex(value) ? decodeU8a(registry, u8aToU8a(value)) : isBn(value) || isNumber(value) || isBigInt(value) ? registry.createTypeUnsafe('AccountIndex', [value]) : decodeString(registry, value);
34}
35/**
36 * @name GenericEthereumLookupSource
37 * @description
38 * A wrapper around an EthereumAccountId and/or AccountIndex that is encoded with a prefix.
39 * Since we are dealing with underlying publicKeys (or shorter encoded addresses),
40 * we extend from Base with an AccountId/AccountIndex wrapper. Basically the Address
41 * is encoded as `[ <prefix-byte>, ...publicKey/...bytes ]` as per spec
42 */
43
44
45export class GenericEthereumLookupSource extends Base {
46 constructor(registry, value = new Uint8Array()) {
47 super(registry, decodeAddressOrIndex(registry, value));
48 }
49 /**
50 * @description The length of the value when encoded as a Uint8Array
51 */
52
53
54 get encodedLength() {
55 const rawLength = this._rawLength;
56 return rawLength + ( // for 1 byte AccountIndexes, we are not adding a specific prefix
57 rawLength > 1 ? 1 : 0);
58 }
59 /**
60 * @description The length of the raw value, either AccountIndex or AccountId
61 */
62
63
64 get _rawLength() {
65 return this.inner instanceof GenericAccountIndex ? GenericAccountIndex.calcLength(this.inner) : this.inner.encodedLength;
66 }
67 /**
68 * @description Returns a hex string representation of the value
69 */
70
71
72 toHex() {
73 return u8aToHex(this.toU8a());
74 }
75 /**
76 * @description Returns the base runtime type name for this instance
77 */
78
79
80 toRawType() {
81 return 'Address';
82 }
83 /**
84 * @description Encodes the value as a Uint8Array as per the SCALE specifications
85 * @param isBare true when the value has none of the type-specific prefixes (internal)
86 */
87
88
89 toU8a(isBare) {
90 const encoded = this.inner.toU8a().subarray(0, this._rawLength);
91 return isBare ? encoded : u8aConcat(this.inner instanceof GenericAccountIndex ? GenericAccountIndex.writeLength(encoded) : ACCOUNT_ID_PREFIX, encoded);
92 }
93
94}
\No newline at end of file