-
Notifications
You must be signed in to change notification settings - Fork 774
/
Copy pathaddress.ts
157 lines (142 loc) · 3.88 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
import {
generateAddress,
generateAddress2,
isValidAddress,
privateToAddress,
pubToAddress,
} from './account.js'
import {
bigIntToBytes,
bytesToBigInt,
bytesToHex,
equalsBytes,
hexToBytes,
setLengthLeft,
} from './bytes.js'
import { BIGINT_0 } from './constants.js'
import type { PrefixedHexString } from './types.js'
/**
* Handling and generating Ethereum addresses
*/
export class Address {
public readonly bytes: Uint8Array
constructor(bytes: Uint8Array) {
if (bytes.length !== 20) {
throw new Error('Invalid address length')
}
this.bytes = bytes
}
/**
* Is address equal to another.
*/
equals(address: Address): boolean {
return equalsBytes(this.bytes, address.bytes)
}
/**
* Is address zero.
*/
isZero(): boolean {
return this.equals(new Address(new Uint8Array(20)))
}
/**
* True if address is in the address range defined
* by EIP-1352
*/
isPrecompileOrSystemAddress(): boolean {
const address = bytesToBigInt(this.bytes)
const rangeMin = BIGINT_0
const rangeMax = BigInt('0xffff')
return address >= rangeMin && address <= rangeMax
}
/**
* Returns hex encoding of address.
*/
toString(): PrefixedHexString {
return bytesToHex(this.bytes)
}
/**
* Returns a new Uint8Array representation of address.
*/
toBytes(): Uint8Array {
return new Uint8Array(this.bytes)
}
}
/**
* Returns the zero address.
*/
export function createZeroAddress(): Address {
return new Address(new Uint8Array(20))
}
/**
* Returns an Address object from a bigint address (they are stored as bigints on the stack)
* @param value The bigint address
*/
export function createAddressFromBigInt(value: bigint): Address {
const bytes = bigIntToBytes(value)
if (bytes.length > 20) {
throw new Error(`Invalid address, too long: ${bytes.length}`)
}
return new Address(setLengthLeft(bytes, 20))
}
/**
* Returns an Address object from a hex-encoded string.
* @param str - Hex-encoded address
*/
export function createAddressFromString(str: string): Address {
if (!isValidAddress(str)) {
throw new Error(`Invalid address input=${str}`)
}
return new Address(hexToBytes(str))
}
/**
* Returns an address for a given public key.
* @param pubKey The two points of an uncompressed key
*/
export function createAddressFromPublicKey(pubKey: Uint8Array): Address {
if (!(pubKey instanceof Uint8Array)) {
throw new Error('Public key should be Uint8Array')
}
const bytes = pubToAddress(pubKey)
return new Address(bytes)
}
/**
* Returns an address for a given private key.
* @param privateKey A private key must be 256 bits wide
*/
export function createAddressFromPrivateKey(privateKey: Uint8Array): Address {
if (!(privateKey instanceof Uint8Array)) {
throw new Error('Private key should be Uint8Array')
}
const bytes = privateToAddress(privateKey)
return new Address(bytes)
}
/**
* Generates an address for a newly created contract.
* @param from The address which is creating this new address
* @param nonce The nonce of the from account
*/
export function createContractAddress(from: Address, nonce: bigint): Address {
if (typeof nonce !== 'bigint') {
throw new Error('Expected nonce to be a bigint')
}
return new Address(generateAddress(from.bytes, bigIntToBytes(nonce)))
}
/**
* Generates an address for a contract created using CREATE2.
* @param from The address which is creating this new address
* @param salt A salt
* @param initCode The init code of the contract being created
*/
export function createContractAddress2(
from: Address,
salt: Uint8Array,
initCode: Uint8Array,
): Address {
if (!(salt instanceof Uint8Array)) {
throw new Error('Expected salt to be a Uint8Array')
}
if (!(initCode instanceof Uint8Array)) {
throw new Error('Expected initCode to be a Uint8Array')
}
return new Address(generateAddress2(from.bytes, salt, initCode))
}