-
Notifications
You must be signed in to change notification settings - Fork 54
/
BaseAddress.ts
153 lines (135 loc) · 4.87 KB
/
BaseAddress.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
/* eslint-disable no-bitwise */
import { Address, AddressProps, AddressType, Credential, CredentialType } from './Address';
import { Hash28ByteBase16 } from '@cardano-sdk/crypto';
import { InvalidArgumentError } from '@cardano-sdk/util';
import { NetworkId } from '../ChainId';
/**
* A base address directly specifies the stake key that should control the stake for that address. The staking rights
* associated with funds held in this address may be exercised by the owner of the stake key. Base addresses can be
* used in transactions without registering the stake key in advance.
*
* The stake rights can only be exercised by registering the stake key and delegating to a stake pool. Once the stake
* key is registered, the stake rights can be exercised for base addresses used in transactions before or after the key
* registration.
*/
export class BaseAddress {
readonly #type: AddressType;
readonly #networkId: NetworkId;
readonly #paymentPart: Credential;
readonly #delegationPart: Credential;
/**
* Initializes a new instance of the BaseAddress class.
*
* @param props The address properties.
* @private
*/
private constructor(props: AddressProps) {
this.#networkId = props.networkId!;
this.#paymentPart = props.paymentPart!;
this.#delegationPart = props.delegationPart!;
this.#type = props.type;
}
/**
* Creates a new instance of the BaseAddress from its credentials.
*
* @param networkId The Network identifier.
* @param payment The payment credential.
* @param stake The stake credential.
*/
static fromCredentials(networkId: NetworkId, payment: Credential, stake: Credential): BaseAddress {
let type = AddressType.BasePaymentKeyStakeKey;
if (payment.type === CredentialType.ScriptHash) type |= 0b0001;
if (stake.type === CredentialType.ScriptHash) type |= 0b0010;
return new BaseAddress({
delegationPart: stake,
networkId,
paymentPart: payment,
type
});
}
/** Gets the payment credential part of the base address. */
getPaymentCredential(): Credential {
return this.#paymentPart;
}
/** Gets the stake credential part of the base address. */
getStakeCredential(): Credential {
return this.#delegationPart;
}
/** Converts from BaseAddress instance to Address. */
toAddress(): Address {
return new Address({
delegationPart: this.#delegationPart,
networkId: this.#networkId,
paymentPart: this.#paymentPart,
type: this.#type
});
}
/**
* Creates a BaseAddress address from an Address instance.
*
* @param addr The address instance to be converted.
* @returns The BaseAddress instance or undefined if Address is not a valid BaseAddress.
*/
static fromAddress(addr: Address): BaseAddress | undefined {
let address;
switch (addr.getProps().type) {
case AddressType.BasePaymentKeyStakeKey:
case AddressType.BasePaymentScriptStakeKey:
case AddressType.BasePaymentKeyStakeScript:
case AddressType.BasePaymentScriptStakeScript:
address = new BaseAddress(addr.getProps());
break;
default:
}
return address;
}
/**
* Packs the base address into its raw binary format.
*
* @param props The address properties.
*/
static packParts(props: AddressProps): Buffer {
return Buffer.concat([
Buffer.from([(props.type << 4) | props.networkId!]),
Buffer.from(props.paymentPart!.hash, 'hex'),
Buffer.from(props.delegationPart!.hash, 'hex')
]);
}
/**
* There are currently 4 types of Shelley Base addresses, summarized below:
*
* - 0000 PaymentKeyHash StakeKeyHash
* - 0001 ScriptHash StakeKeyHash
* - 0010 PaymentKeyHash ScriptHash
* - 0011 ScriptHash ScriptHash
*
* @param type The address type.
* @param data The serialized address data.
*/
static unpackParts(type: number, data: Uint8Array): Address {
if (data.length !== 57) throw new InvalidArgumentError('data', 'Base address data length should be 57 bytes long.');
const network = data[0] & 0b0000_1111;
const paymentCredential = Hash28ByteBase16(Buffer.from(data.slice(1, 29)).toString('hex'));
const stakeCredential = Hash28ByteBase16(Buffer.from(data.slice(29, 57)).toString('hex'));
const delegationCredType =
type === AddressType.BasePaymentKeyStakeScript || type === AddressType.BasePaymentScriptStakeScript
? CredentialType.ScriptHash
: CredentialType.KeyHash;
const paymentCredType =
type === AddressType.BasePaymentScriptStakeKey || type === AddressType.BasePaymentScriptStakeScript
? CredentialType.ScriptHash
: CredentialType.KeyHash;
return new Address({
delegationPart: {
hash: stakeCredential,
type: delegationCredType
},
networkId: network,
paymentPart: {
hash: paymentCredential,
type: paymentCredType
},
type
});
}
}