@stacks/network 6.12.1-pr.fa55638.0 → 6.12.2-pr.b00840a.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/network.ts CHANGED
@@ -1,67 +1,215 @@
1
- import { DEVNET_URL, HIRO_MAINNET_URL, HIRO_TESTNET_URL } from '@stacks/common';
2
- import { ChainId, PeerNetworkId, TransactionVersion } from './constants';
3
-
4
- export interface StacksNetwork {
5
- chainId: number;
6
- transactionVersion: number; // todo: txVersion better?
7
- peerNetworkId: number;
8
- magicBytes: string;
9
- // todo: add check32 character bytes string
10
- }
1
+ import { TransactionVersion, ChainID } from '@stacks/common';
2
+ import { createFetchFn, FetchFn } from './fetch';
3
+
4
+ export const HIRO_MAINNET_DEFAULT = 'https://api.mainnet.hiro.so';
5
+ export const HIRO_TESTNET_DEFAULT = 'https://api.testnet.hiro.so';
6
+ export const HIRO_MOCKNET_DEFAULT = 'http://localhost:3999';
11
7
 
12
- export const STACKS_MAINNET: StacksNetwork = {
13
- chainId: ChainId.Mainnet,
14
- transactionVersion: TransactionVersion.Mainnet,
15
- peerNetworkId: PeerNetworkId.Mainnet,
16
- magicBytes: 'X2', // todo: comment bytes version of magic bytes
17
- };
18
-
19
- export const STACKS_TESTNET: StacksNetwork = {
20
- chainId: ChainId.Testnet,
21
- transactionVersion: TransactionVersion.Testnet,
22
- peerNetworkId: PeerNetworkId.Testnet,
23
- magicBytes: 'T2', // todo: comment bytes version of magic bytes
24
- };
25
-
26
- export const STACKS_DEVNET: StacksNetwork = {
27
- ...STACKS_TESTNET,
28
- magicBytes: 'id', // todo: comment bytes version of magic bytes
29
- };
30
- export const STACKS_MOCKNET: StacksNetwork = { ...STACKS_DEVNET };
8
+ /**
9
+ * Used for constructing Network instances
10
+ * @related {@link StacksNetwork}, {@link StacksMainnet}, {@link StacksTestnet}, {@link StacksDevnet}, {@link StacksMocknet}
11
+ */
12
+ export interface NetworkConfig {
13
+ /** The base API/node URL for the network fetch calls */
14
+ url: string;
15
+ /** An optional custom fetch function to override default behaviors */
16
+ fetchFn?: FetchFn;
17
+ }
31
18
 
32
19
  /** @ignore internal */
33
20
  export const StacksNetworks = ['mainnet', 'testnet', 'devnet', 'mocknet'] as const;
34
21
  /** The enum-style names of different common Stacks networks */
35
22
  export type StacksNetworkName = (typeof StacksNetworks)[number];
36
23
 
37
- export function networkFromName(name: StacksNetworkName) {
38
- switch (name) {
39
- case 'mainnet':
40
- return STACKS_MAINNET;
41
- case 'testnet':
42
- return STACKS_TESTNET;
43
- case 'devnet':
44
- return STACKS_DEVNET;
45
- case 'mocknet':
46
- return STACKS_MOCKNET;
47
- default:
48
- throw new Error(`Unknown network name: ${name}`);
24
+ /**
25
+ * The base class for Stacks networks. Typically used via its subclasses.
26
+ * @related {@link StacksMainnet}, {@link StacksTestnet}, {@link StacksDevnet}, {@link StacksMocknet}
27
+ */
28
+ export class StacksNetwork {
29
+ version: TransactionVersion = TransactionVersion.Mainnet;
30
+ chainId: ChainID = ChainID.Mainnet;
31
+ bnsLookupUrl = 'https://api.mainnet.hiro.so';
32
+ broadcastEndpoint = '/v2/transactions';
33
+ transferFeeEstimateEndpoint = '/v2/fees/transfer';
34
+ transactionFeeEstimateEndpoint = '/v2/fees/transaction';
35
+ accountEndpoint = '/v2/accounts';
36
+ contractAbiEndpoint = '/v2/contracts/interface';
37
+ readOnlyFunctionCallEndpoint = '/v2/contracts/call-read';
38
+
39
+ readonly coreApiUrl: string;
40
+
41
+ fetchFn: FetchFn;
42
+
43
+ constructor(networkConfig: NetworkConfig) {
44
+ this.coreApiUrl = networkConfig.url;
45
+ this.fetchFn = networkConfig.fetchFn ?? createFetchFn();
46
+ }
47
+
48
+ /** A static network constructor from a network name */
49
+ static fromName = (networkName: StacksNetworkName): StacksNetwork => {
50
+ switch (networkName) {
51
+ case 'mainnet':
52
+ return new StacksMainnet();
53
+ case 'testnet':
54
+ return new StacksTestnet();
55
+ case 'devnet':
56
+ return new StacksDevnet();
57
+ case 'mocknet':
58
+ return new StacksMocknet();
59
+ default:
60
+ throw new Error(
61
+ `Invalid network name provided. Must be one of the following: ${StacksNetworks.join(
62
+ ', '
63
+ )}`
64
+ );
65
+ }
66
+ };
67
+
68
+ /** @ignore internal */
69
+ static fromNameOrNetwork = (network: StacksNetworkName | StacksNetwork) => {
70
+ if (typeof network !== 'string' && 'version' in network) {
71
+ return network;
72
+ }
73
+
74
+ return StacksNetwork.fromName(network);
75
+ };
76
+
77
+ /** Returns `true` if the network is configured to 'mainnet', based on the TransactionVersion */
78
+ isMainnet = () => this.version === TransactionVersion.Mainnet;
79
+ getBroadcastApiUrl = () => `${this.coreApiUrl}${this.broadcastEndpoint}`;
80
+ getTransferFeeEstimateApiUrl = () => `${this.coreApiUrl}${this.transferFeeEstimateEndpoint}`;
81
+ getTransactionFeeEstimateApiUrl = () =>
82
+ `${this.coreApiUrl}${this.transactionFeeEstimateEndpoint}`;
83
+ getAccountApiUrl = (address: string) =>
84
+ `${this.coreApiUrl}${this.accountEndpoint}/${address}?proof=0`;
85
+ getAccountExtendedBalancesApiUrl = (address: string) =>
86
+ `${this.coreApiUrl}/extended/v1/address/${address}/balances`;
87
+ getAbiApiUrl = (address: string, contract: string) =>
88
+ `${this.coreApiUrl}${this.contractAbiEndpoint}/${address}/${contract}`;
89
+ getReadOnlyFunctionCallApiUrl = (
90
+ contractAddress: string,
91
+ contractName: string,
92
+ functionName: string
93
+ ) =>
94
+ `${this.coreApiUrl}${
95
+ this.readOnlyFunctionCallEndpoint
96
+ }/${contractAddress}/${contractName}/${encodeURIComponent(functionName)}`;
97
+ getInfoUrl = () => `${this.coreApiUrl}/v2/info`;
98
+ getBlockTimeInfoUrl = () => `${this.coreApiUrl}/extended/v1/info/network_block_times`;
99
+ getPoxInfoUrl = () => `${this.coreApiUrl}/v2/pox`;
100
+ getRewardsUrl = (address: string, options?: any) => {
101
+ let url = `${this.coreApiUrl}/extended/v1/burnchain/rewards/${address}`;
102
+ if (options) {
103
+ url = `${url}?limit=${options.limit}&offset=${options.offset}`;
104
+ }
105
+ return url;
106
+ };
107
+ getRewardsTotalUrl = (address: string) =>
108
+ `${this.coreApiUrl}/extended/v1/burnchain/rewards/${address}/total`;
109
+ getRewardHoldersUrl = (address: string, options?: any) => {
110
+ let url = `${this.coreApiUrl}/extended/v1/burnchain/reward_slot_holders/${address}`;
111
+ if (options) {
112
+ url = `${url}?limit=${options.limit}&offset=${options.offset}`;
113
+ }
114
+ return url;
115
+ };
116
+ getStackerInfoUrl = (contractAddress: string, contractName: string) =>
117
+ `${this.coreApiUrl}${this.readOnlyFunctionCallEndpoint}
118
+ ${contractAddress}/${contractName}/get-stacker-info`;
119
+ getDataVarUrl = (contractAddress: string, contractName: string, dataVarName: string) =>
120
+ `${this.coreApiUrl}/v2/data_var/${contractAddress}/${contractName}/${dataVarName}?proof=0`;
121
+ getMapEntryUrl = (contractAddress: string, contractName: string, mapName: string) =>
122
+ `${this.coreApiUrl}/v2/map_entry/${contractAddress}/${contractName}/${mapName}?proof=0`;
123
+ getNameInfo(fullyQualifiedName: string) {
124
+ /*
125
+ TODO: Update to v2 API URL for name lookups
126
+ */
127
+ const nameLookupURL = `${this.bnsLookupUrl}/v1/names/${fullyQualifiedName}`;
128
+ return this.fetchFn(nameLookupURL)
129
+ .then(resp => {
130
+ if (resp.status === 404) {
131
+ throw new Error('Name not found');
132
+ } else if (resp.status !== 200) {
133
+ throw new Error(`Bad response status: ${resp.status}`);
134
+ } else {
135
+ return resp.json();
136
+ }
137
+ })
138
+ .then(nameInfo => {
139
+ // the returned address _should_ be in the correct network ---
140
+ // stacks node gets into trouble because it tries to coerce back to mainnet
141
+ // and the regtest transaction generation libraries want to use testnet addresses
142
+ if (nameInfo.address) {
143
+ return Object.assign({}, nameInfo, { address: nameInfo.address });
144
+ } else {
145
+ return nameInfo;
146
+ }
147
+ });
49
148
  }
50
149
  }
51
150
 
52
- export function networkFrom(network: StacksNetworkName | StacksNetwork) {
53
- if (typeof network === 'string') return networkFromName(network);
54
- return network;
151
+ /**
152
+ * A {@link StacksNetwork} with the parameters for the Stacks mainnet.
153
+ * Pass a `url` option to override the default Hiro hosted Stacks node API.
154
+ * Pass a `fetchFn` option to customize the default networking functions.
155
+ * @example
156
+ * ```
157
+ * const network = new StacksMainnet();
158
+ * const network = new StacksMainnet({ url: "https://api.mainnet.hiro.so" });
159
+ * const network = new StacksMainnet({ fetch: createFetchFn() });
160
+ * ```
161
+ * @related {@link createFetchFn}, {@link createApiKeyMiddleware}
162
+ */
163
+ export class StacksMainnet extends StacksNetwork {
164
+ version = TransactionVersion.Mainnet;
165
+ chainId = ChainID.Mainnet;
166
+
167
+ constructor(opts?: Partial<NetworkConfig>) {
168
+ super({
169
+ url: opts?.url ?? HIRO_MAINNET_DEFAULT,
170
+ fetchFn: opts?.fetchFn,
171
+ });
172
+ }
55
173
  }
56
174
 
57
- export function deriveDefaultUrl(network: StacksNetwork | StacksNetworkName | undefined) {
58
- if (!network) return HIRO_MAINNET_URL; // default to mainnet if no network is given
175
+ /**
176
+ * A {@link StacksNetwork} with the parameters for the Stacks testnet.
177
+ * Pass a `url` option to override the default Hiro hosted Stacks node API.
178
+ * Pass a `fetchFn` option to customize the default networking functions.
179
+ * @example
180
+ * ```
181
+ * const network = new StacksTestnet();
182
+ * const network = new StacksTestnet({ url: "https://api.testnet.hiro.so" });
183
+ * const network = new StacksTestnet({ fetch: createFetchFn() });
184
+ * ```
185
+ * @related {@link createFetchFn}, {@link createApiKeyMiddleware}
186
+ */
187
+ export class StacksTestnet extends StacksNetwork {
188
+ version = TransactionVersion.Testnet;
189
+ chainId = ChainID.Testnet;
59
190
 
60
- network = networkFrom(network);
191
+ constructor(opts?: Partial<NetworkConfig>) {
192
+ super({
193
+ url: opts?.url ?? HIRO_TESTNET_DEFAULT,
194
+ fetchFn: opts?.fetchFn,
195
+ });
196
+ }
197
+ }
198
+
199
+ /**
200
+ * A {@link StacksNetwork} using the testnet parameters, but `localhost:3999` as the API URL.
201
+ */
202
+ export class StacksMocknet extends StacksNetwork {
203
+ version = TransactionVersion.Testnet;
204
+ chainId = ChainID.Testnet;
61
205
 
62
- return !network || network.transactionVersion === TransactionVersion.Mainnet
63
- ? HIRO_MAINNET_URL // default to mainnet if txVersion is mainnet
64
- : network.magicBytes === 'id'
65
- ? DEVNET_URL // default to devnet if magicBytes are devnet
66
- : HIRO_TESTNET_URL;
206
+ constructor(opts?: Partial<NetworkConfig>) {
207
+ super({
208
+ url: opts?.url ?? HIRO_MOCKNET_DEFAULT,
209
+ fetchFn: opts?.fetchFn,
210
+ });
211
+ }
67
212
  }
213
+
214
+ /** Alias for {@link StacksMocknet} */
215
+ export const StacksDevnet = StacksMocknet;
@@ -1,15 +0,0 @@
1
- export declare enum ChainId {
2
- Mainnet = 1,
3
- Testnet = 2147483648
4
- }
5
- export declare enum PeerNetworkId {
6
- Mainnet = 385875968,
7
- Testnet = 4278190080
8
- }
9
- export declare const DEFAULT_CHAIN_ID = ChainId.Mainnet;
10
- export declare enum TransactionVersion {
11
- Mainnet = 0,
12
- Testnet = 128
13
- }
14
- export declare const DEFAULT_TRANSACTION_VERSION = TransactionVersion.Mainnet;
15
- export declare function whenTransactionVersion(transactionVersion: TransactionVersion): <T>(map: Record<TransactionVersion, T>) => T;
package/dist/constants.js DELETED
@@ -1,25 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.whenTransactionVersion = exports.DEFAULT_TRANSACTION_VERSION = exports.TransactionVersion = exports.DEFAULT_CHAIN_ID = exports.PeerNetworkId = exports.ChainId = void 0;
4
- var ChainId;
5
- (function (ChainId) {
6
- ChainId[ChainId["Mainnet"] = 1] = "Mainnet";
7
- ChainId[ChainId["Testnet"] = 2147483648] = "Testnet";
8
- })(ChainId || (exports.ChainId = ChainId = {}));
9
- var PeerNetworkId;
10
- (function (PeerNetworkId) {
11
- PeerNetworkId[PeerNetworkId["Mainnet"] = 385875968] = "Mainnet";
12
- PeerNetworkId[PeerNetworkId["Testnet"] = 4278190080] = "Testnet";
13
- })(PeerNetworkId || (exports.PeerNetworkId = PeerNetworkId = {}));
14
- exports.DEFAULT_CHAIN_ID = ChainId.Mainnet;
15
- var TransactionVersion;
16
- (function (TransactionVersion) {
17
- TransactionVersion[TransactionVersion["Mainnet"] = 0] = "Mainnet";
18
- TransactionVersion[TransactionVersion["Testnet"] = 128] = "Testnet";
19
- })(TransactionVersion || (exports.TransactionVersion = TransactionVersion = {}));
20
- exports.DEFAULT_TRANSACTION_VERSION = TransactionVersion.Mainnet;
21
- function whenTransactionVersion(transactionVersion) {
22
- return (map) => map[transactionVersion];
23
- }
24
- exports.whenTransactionVersion = whenTransactionVersion;
25
- //# sourceMappingURL=constants.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":";;;AAIA,IAAY,OAGX;AAHD,WAAY,OAAO;IACjB,2CAAoB,CAAA;IACpB,oDAAoB,CAAA;AACtB,CAAC,EAHW,OAAO,uBAAP,OAAO,QAGlB;AAYD,IAAY,aAGX;AAHD,WAAY,aAAa;IACvB,+DAAoB,CAAA;IACpB,gEAAoB,CAAA;AACtB,CAAC,EAHW,aAAa,6BAAb,aAAa,QAGxB;AAEY,QAAA,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;AAOhD,IAAY,kBAGX;AAHD,WAAY,kBAAkB;IAC5B,iEAAc,CAAA;IACd,mEAAc,CAAA;AAChB,CAAC,EAHW,kBAAkB,kCAAlB,kBAAkB,QAG7B;AAEY,QAAA,2BAA2B,GAAG,kBAAkB,CAAC,OAAO,CAAC;AAGtE,SAAgB,sBAAsB,CAAC,kBAAsC;IAC3E,OAAO,CAAI,GAAkC,EAAK,EAAE,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;AAC/E,CAAC;AAFD,wDAEC"}
@@ -1,15 +0,0 @@
1
- export declare enum ChainId {
2
- Mainnet = 1,
3
- Testnet = 2147483648
4
- }
5
- export declare enum PeerNetworkId {
6
- Mainnet = 385875968,
7
- Testnet = 4278190080
8
- }
9
- export declare const DEFAULT_CHAIN_ID = ChainId.Mainnet;
10
- export declare enum TransactionVersion {
11
- Mainnet = 0,
12
- Testnet = 128
13
- }
14
- export declare const DEFAULT_TRANSACTION_VERSION = TransactionVersion.Mainnet;
15
- export declare function whenTransactionVersion(transactionVersion: TransactionVersion): <T>(map: Record<TransactionVersion, T>) => T;
@@ -1,21 +0,0 @@
1
- export var ChainId;
2
- (function (ChainId) {
3
- ChainId[ChainId["Mainnet"] = 1] = "Mainnet";
4
- ChainId[ChainId["Testnet"] = 2147483648] = "Testnet";
5
- })(ChainId || (ChainId = {}));
6
- export var PeerNetworkId;
7
- (function (PeerNetworkId) {
8
- PeerNetworkId[PeerNetworkId["Mainnet"] = 385875968] = "Mainnet";
9
- PeerNetworkId[PeerNetworkId["Testnet"] = 4278190080] = "Testnet";
10
- })(PeerNetworkId || (PeerNetworkId = {}));
11
- export const DEFAULT_CHAIN_ID = ChainId.Mainnet;
12
- export var TransactionVersion;
13
- (function (TransactionVersion) {
14
- TransactionVersion[TransactionVersion["Mainnet"] = 0] = "Mainnet";
15
- TransactionVersion[TransactionVersion["Testnet"] = 128] = "Testnet";
16
- })(TransactionVersion || (TransactionVersion = {}));
17
- export const DEFAULT_TRANSACTION_VERSION = TransactionVersion.Mainnet;
18
- export function whenTransactionVersion(transactionVersion) {
19
- return (map) => map[transactionVersion];
20
- }
21
- //# sourceMappingURL=constants.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAIA,MAAM,CAAN,IAAY,OAGX;AAHD,WAAY,OAAO;IACjB,2CAAoB,CAAA;IACpB,oDAAoB,CAAA;AACtB,CAAC,EAHW,OAAO,KAAP,OAAO,QAGlB;AAYD,MAAM,CAAN,IAAY,aAGX;AAHD,WAAY,aAAa;IACvB,+DAAoB,CAAA;IACpB,gEAAoB,CAAA;AACtB,CAAC,EAHW,aAAa,KAAb,aAAa,QAGxB;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;AAOhD,MAAM,CAAN,IAAY,kBAGX;AAHD,WAAY,kBAAkB;IAC5B,iEAAc,CAAA;IACd,mEAAc,CAAA;AAChB,CAAC,EAHW,kBAAkB,KAAlB,kBAAkB,QAG7B;AAED,MAAM,CAAC,MAAM,2BAA2B,GAAG,kBAAkB,CAAC,OAAO,CAAC;AAGtE,MAAM,UAAU,sBAAsB,CAAC,kBAAsC;IAC3E,OAAO,CAAI,GAAkC,EAAK,EAAE,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;AAC/E,CAAC"}
package/src/constants.ts DELETED
@@ -1,42 +0,0 @@
1
- /**
2
- * The chain ID (unsigned 32-bit integer), used so transactions can't be replayed on other chains.
3
- * Similar to the {@link TransactionVersion}.
4
- */
5
- export enum ChainId {
6
- Mainnet = 0x00000001,
7
- Testnet = 0x80000000,
8
- }
9
-
10
- /**
11
- * The **peer** network ID.
12
- * Typically not used in signing, but used for broadcasting to the P2P network.
13
- * It can also be used to determine the parent of a subnet.
14
- *
15
- * **Attention:**
16
- * For mainnet/testnet the v2/info response `.network_id` refers to the chain ID.
17
- * For subnets the v2/info response `.network_id` refers to the peer network ID and the chain ID (they are the same for subnets).
18
- * The `.parent_network_id` refers to the actual peer network ID (of the parent) in both cases.
19
- */
20
- export enum PeerNetworkId {
21
- Mainnet = 0x17000000,
22
- Testnet = 0xff000000,
23
- }
24
-
25
- export const DEFAULT_CHAIN_ID = ChainId.Mainnet;
26
-
27
- /**
28
- * The transaction version, used so transactions can't be replayed on other networks.
29
- * Similar to the {@link ChainId}.
30
- * Used internally for serializing and deserializing transactions.
31
- */
32
- export enum TransactionVersion {
33
- Mainnet = 0x00,
34
- Testnet = 0x80,
35
- }
36
-
37
- export const DEFAULT_TRANSACTION_VERSION = TransactionVersion.Mainnet;
38
-
39
- /** @ignore */
40
- export function whenTransactionVersion(transactionVersion: TransactionVersion) {
41
- return <T>(map: Record<TransactionVersion, T>): T => map[transactionVersion];
42
- }