@stacks/network 4.0.2 → 4.2.0-beta.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 ADDED
@@ -0,0 +1,178 @@
1
+ import { TransactionVersion, ChainID } from '@stacks/common';
2
+ import { createFetchFn, FetchFn } from './fetch';
3
+
4
+ export const HIRO_MAINNET_DEFAULT = 'https://stacks-node-api.mainnet.stacks.co';
5
+ export const HIRO_TESTNET_DEFAULT = 'https://stacks-node-api.testnet.stacks.co';
6
+ export const HIRO_MOCKNET_DEFAULT = 'http://localhost:3999';
7
+
8
+ export interface NetworkConfig {
9
+ url: string;
10
+ fetchFn?: FetchFn;
11
+ }
12
+
13
+ export const StacksNetworks = ['mainnet', 'testnet'] as const;
14
+ export type StacksNetworkName = typeof StacksNetworks[number];
15
+
16
+ /**
17
+ * @related {@link StacksMainnet}, {@link StacksTestnet}, {@link StacksMocknet}
18
+ */
19
+ export class StacksNetwork {
20
+ version = TransactionVersion.Mainnet;
21
+ chainId = ChainID.Mainnet;
22
+ bnsLookupUrl = 'https://stacks-node-api.mainnet.stacks.co';
23
+ broadcastEndpoint = '/v2/transactions';
24
+ transferFeeEstimateEndpoint = '/v2/fees/transfer';
25
+ transactionFeeEstimateEndpoint = '/v2/fees/transaction';
26
+ accountEndpoint = '/v2/accounts';
27
+ contractAbiEndpoint = '/v2/contracts/interface';
28
+ readOnlyFunctionCallEndpoint = '/v2/contracts/call-read';
29
+
30
+ readonly coreApiUrl: string;
31
+
32
+ fetchFn: FetchFn;
33
+
34
+ constructor(networkConfig: NetworkConfig) {
35
+ this.coreApiUrl = networkConfig.url;
36
+ this.fetchFn = networkConfig.fetchFn ?? createFetchFn();
37
+ }
38
+
39
+ static fromName = (networkName: StacksNetworkName): StacksNetwork => {
40
+ switch (networkName) {
41
+ case 'mainnet':
42
+ return new StacksMainnet();
43
+ case 'testnet':
44
+ return new StacksTestnet();
45
+ default:
46
+ throw new Error(
47
+ `Invalid network name provided. Must be one of the following: ${StacksNetworks.join(
48
+ ', '
49
+ )}`
50
+ );
51
+ }
52
+ };
53
+
54
+ static fromNameOrNetwork = (network: StacksNetworkName | StacksNetwork) => {
55
+ if (typeof network !== 'string' && 'version' in network) {
56
+ return network;
57
+ }
58
+
59
+ return StacksNetwork.fromName(network);
60
+ };
61
+
62
+ isMainnet = () => this.version === TransactionVersion.Mainnet;
63
+ getBroadcastApiUrl = () => `${this.coreApiUrl}${this.broadcastEndpoint}`;
64
+ getTransferFeeEstimateApiUrl = () => `${this.coreApiUrl}${this.transferFeeEstimateEndpoint}`;
65
+ getTransactionFeeEstimateApiUrl = () =>
66
+ `${this.coreApiUrl}${this.transactionFeeEstimateEndpoint}`;
67
+ getAccountApiUrl = (address: string) =>
68
+ `${this.coreApiUrl}${this.accountEndpoint}/${address}?proof=0`;
69
+ getAbiApiUrl = (address: string, contract: string) =>
70
+ `${this.coreApiUrl}${this.contractAbiEndpoint}/${address}/${contract}`;
71
+ getReadOnlyFunctionCallApiUrl = (
72
+ contractAddress: string,
73
+ contractName: string,
74
+ functionName: string
75
+ ) =>
76
+ `${this.coreApiUrl}${
77
+ this.readOnlyFunctionCallEndpoint
78
+ }/${contractAddress}/${contractName}/${encodeURIComponent(functionName)}`;
79
+ getInfoUrl = () => `${this.coreApiUrl}/v2/info`;
80
+ getBlockTimeInfoUrl = () => `${this.coreApiUrl}/extended/v1/info/network_block_times`;
81
+ getPoxInfoUrl = () => `${this.coreApiUrl}/v2/pox`;
82
+ getRewardsUrl = (address: string, options?: any) => {
83
+ let url = `${this.coreApiUrl}/extended/v1/burnchain/rewards/${address}`;
84
+ if (options) {
85
+ url = `${url}?limit=${options.limit}&offset=${options.offset}`;
86
+ }
87
+ return url;
88
+ };
89
+ getRewardsTotalUrl = (address: string) =>
90
+ `${this.coreApiUrl}/extended/v1/burnchain/rewards/${address}/total`;
91
+ getRewardHoldersUrl = (address: string, options?: any) => {
92
+ let url = `${this.coreApiUrl}/extended/v1/burnchain/reward_slot_holders/${address}`;
93
+ if (options) {
94
+ url = `${url}?limit=${options.limit}&offset=${options.offset}`;
95
+ }
96
+ return url;
97
+ };
98
+ getStackerInfoUrl = (contractAddress: string, contractName: string) =>
99
+ `${this.coreApiUrl}${this.readOnlyFunctionCallEndpoint}
100
+ ${contractAddress}/${contractName}/get-stacker-info`;
101
+ getNameInfo(fullyQualifiedName: string) {
102
+ /*
103
+ TODO: Update to v2 API URL for name lookups
104
+ */
105
+ const nameLookupURL = `${this.bnsLookupUrl}/v1/names/${fullyQualifiedName}`;
106
+ return this.fetchFn(nameLookupURL)
107
+ .then(resp => {
108
+ if (resp.status === 404) {
109
+ throw new Error('Name not found');
110
+ } else if (resp.status !== 200) {
111
+ throw new Error(`Bad response status: ${resp.status}`);
112
+ } else {
113
+ return resp.json();
114
+ }
115
+ })
116
+ .then(nameInfo => {
117
+ // the returned address _should_ be in the correct network ---
118
+ // blockstackd gets into trouble because it tries to coerce back to mainnet
119
+ // and the regtest transaction generation libraries want to use testnet addresses
120
+ if (nameInfo.address) {
121
+ return Object.assign({}, nameInfo, { address: nameInfo.address });
122
+ } else {
123
+ return nameInfo;
124
+ }
125
+ });
126
+ }
127
+ }
128
+
129
+ /**
130
+ * A {@link StacksNetwork} with default values for the Stacks mainnet.
131
+ * Pass a `url` option to override the default Hiro hosted Stacks node API.
132
+ * Pass a `fetchFn` option to customize the default networking functions.
133
+ * @example
134
+ * ```
135
+ * const network = new StacksMainnet();
136
+ * const network = new StacksMainnet({ url: "https://stacks-node-api.mainnet.stacks.co" });
137
+ * const network = new StacksMainnet({ fetch: createFetchFn() });
138
+ * ```
139
+ * @related {@link createFetchFn}, {@link createApiKeyMiddleware}
140
+ */
141
+ export class StacksMainnet extends StacksNetwork {
142
+ version = TransactionVersion.Mainnet;
143
+ chainId = ChainID.Mainnet;
144
+
145
+ constructor(opts?: Partial<NetworkConfig>) {
146
+ super({
147
+ url: opts?.url ?? HIRO_MAINNET_DEFAULT,
148
+ fetchFn: opts?.fetchFn,
149
+ });
150
+ }
151
+ }
152
+
153
+ /**
154
+ * Same as {@link StacksMainnet} but defaults to values for the Stacks testnet.
155
+ */
156
+ export class StacksTestnet extends StacksNetwork {
157
+ version = TransactionVersion.Testnet;
158
+ chainId = ChainID.Testnet;
159
+
160
+ constructor(opts?: Partial<NetworkConfig>) {
161
+ super({
162
+ url: opts?.url ?? HIRO_TESTNET_DEFAULT,
163
+ fetchFn: opts?.fetchFn,
164
+ });
165
+ }
166
+ }
167
+
168
+ export class StacksMocknet extends StacksNetwork {
169
+ version = TransactionVersion.Testnet;
170
+ chainId = ChainID.Testnet;
171
+
172
+ constructor(opts?: Partial<NetworkConfig>) {
173
+ super({
174
+ url: opts?.url ?? HIRO_MOCKNET_DEFAULT,
175
+ fetchFn: opts?.fetchFn,
176
+ });
177
+ }
178
+ }