-
Notifications
You must be signed in to change notification settings - Fork 22
/
address.ts
183 lines (146 loc) · 5.62 KB
/
address.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
const Buffer = require('buffer/').Buffer
import { checkParams, ed25519, blake2b, isHexString } from '~@vite/vitejs-utils';
import { addressIllegal } from '~@vite/vitejs-error';
import { Hex, AddressObj, Address } from './type';
const { keyPair, getPublicKey } = ed25519;
export const ADDR_PRE = 'vite_';
export const ADDR_SIZE = 20;
export const ADDR_CHECK_SUM_SIZE = 5;
export const ADDR_LEN = ADDR_PRE.length + ADDR_SIZE * 2 + ADDR_CHECK_SUM_SIZE * 2;
export enum AddressType {
'Illegal' = 0,
'Account',
'Contract'
}
export function createAddressByPrivateKey(privateKey?: Hex): AddressObj {
const err = checkParams({ privateKey }, [], [{
name: 'privateKey',
func: isHexString
}]);
if (err) {
throw err;
}
// originalAddress = Blake2b(PubKey)(len:20) + (isContract ? 1 : 0)(len:1) // There is false
const addressResult = createAddress(privateKey);
const originalAddress = addressResult.originAddress;
// checkSum = isContract ? reverse(Blake2b(address[0:20])(len:5)) : Blake2b(address[0:20])(len:5) // There is false
const checkSum = getAddrCheckSum(originalAddress, false);
// address = 'vite_' + Hex(originalAddress[0:20] + checkSum)
const address = getHexAddr(originalAddress, checkSum);
const publicKey: Buffer = getPublicKey(addressResult.privateKey);
return {
originalAddress: originalAddress.toString('hex'),
publicKey: Buffer.from(publicKey).toString('hex'),
privateKey: addressResult.privateKey.toString('hex'),
address
};
}
export function getAddressFromPublicKey(publicKey: Hex): Address {
const err = checkParams({ publicKey }, ['publicKey'], [{
name: 'publicKey',
func: isHexString
}]);
if (err) {
throw new Error(err.message);
}
const publicKeyBuffer = Buffer.from(publicKey, 'hex');
const originalAddress = newAddrFromPub(publicKeyBuffer);
const checkSum = getAddrCheckSum(originalAddress, false);
return getHexAddr(originalAddress, checkSum);
}
export function getOriginalAddressFromAddress(hexAddr: Hex): Hex {
const addrType = isValidAddress(hexAddr);
if (addrType === AddressType.Illegal) {
throw addressIllegal;
}
return getOriginalAddress(hexAddr, addrType);
}
export function getAddressFromOriginalAddress(originalAddress: Hex): Address {
const err = checkParams({ originalAddress }, ['originalAddress'], [{
name: 'originalAddress',
func: _originalAddress => typeof _originalAddress === 'string' && /^[0-9a-fA-F]+$/.test(_originalAddress) && (_originalAddress.length === ADDR_SIZE * 2 || _originalAddress.length === (ADDR_SIZE + 1) * 2)
}]);
if (err) {
throw new Error(err.message);
}
let contractNum = Number(originalAddress.slice(-2));
contractNum = contractNum !== 0 && contractNum !== 1 ? 0 : contractNum;
const isContract = !!Number(contractNum);
const originalAddressBuf = Buffer.from(originalAddress, 'hex');
const checkSum = getAddrCheckSum(originalAddressBuf, isContract);
return getHexAddr(originalAddressBuf, checkSum);
}
export function isValidAddress(address: Hex): AddressType {
if (!isValidHex(address)) {
return AddressType.Illegal;
}
return isValidCheckSum(address);
}
function getOriginalAddress(hexAddr: Hex, addrType: AddressType): Hex {
const addr = hexAddr.slice(ADDR_PRE.length, ADDR_PRE.length + ADDR_SIZE * 2);
if (addrType === AddressType.Account) {
return `${ addr }00`;
}
return `${ addr }01`;
}
function createAddress(privateKey?: Hex): {
originAddress: Buffer;
privateKey: Buffer;
} {
// Init priveKey
let privateKeyBuffer: Buffer;
if (privateKey) {
privateKeyBuffer = Buffer.from(privateKey, 'hex');
} else {
const _keyPair = keyPair();
privateKeyBuffer = _keyPair.privateKey;
}
return {
originAddress: newAddrFromPriv(privateKeyBuffer),
privateKey: privateKeyBuffer
};
}
function newAddrFromPub(publicKey: Buffer): Buffer {
const _pre = blake2b(publicKey, null, ADDR_SIZE);
const pre = new Uint8Array(21);
pre.set(_pre);
pre.set([0], 20);
return Buffer.from(pre);
}
function newAddrFromPriv(privateKey: Buffer): Buffer {
const publicKey: Buffer = getPublicKey(privateKey);
return newAddrFromPub(Buffer.from(publicKey));
}
function getAddrCheckSum(addr: Buffer, isContract? : boolean): Hex {
const addrPre20 = addr.slice(0, 20);
const _checkSum = blake2b(addrPre20, null, ADDR_CHECK_SUM_SIZE);
const checkSum = Buffer.from(_checkSum);
if (!isContract) {
return checkSum.toString('hex');
}
const newCheckSum = [];
checkSum.forEach(function (byte) {
newCheckSum.push(byte ^ 0xFF);
});
return Buffer.from(newCheckSum).toString('hex');
}
function getHexAddr(originalAddress: Buffer, checkSum: Hex): Address {
return ADDR_PRE + originalAddress.slice(0, 20).toString('hex') + checkSum;
}
function isValidHex(hexAddr: Address): boolean {
return hexAddr && hexAddr.length === ADDR_LEN && hexAddr.indexOf(ADDR_PRE) === 0;
}
function isValidCheckSum(hexAddr: Address): AddressType {
const currentChecksum = hexAddr.slice(ADDR_PRE.length + ADDR_SIZE * 2);
const _addr = hexAddr.slice(ADDR_PRE.length, ADDR_PRE.length + ADDR_SIZE * 2);
const addr = Buffer.from(_addr, 'hex');
const contractCheckSum = getAddrCheckSum(addr, true);
if (contractCheckSum === currentChecksum) {
return AddressType.Contract;
}
const checkSum = getAddrCheckSum(addr);
if (currentChecksum === checkSum) {
return AddressType.Account;
}
return AddressType.Illegal;
}