gn-provider 1.1.8 → 1.2.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.
@@ -5,6 +5,9 @@ declare enum ProviderEvent {
5
5
  Connected = "connected",
6
6
  NetworkChange = "networkChange"
7
7
  }
8
+ export type UTXOWithHeight = UTXO & {
9
+ height: number;
10
+ };
8
11
  export declare class GNProvider extends Provider {
9
12
  emit: (event: ProviderEvent, ...args: any[]) => boolean;
10
13
  private _network;
@@ -21,7 +24,7 @@ export declare class GNProvider extends Provider {
21
24
  protected _ready: () => Promise<void>;
22
25
  sendRawTransaction: (rawTxHex: string) => Promise<TxHash>;
23
26
  sendTransaction: (signedTx: scryptlib.bsv.Transaction) => Promise<string>;
24
- listUnspent: (address: AddressOption, options?: UtxoQueryOptions) => Promise<UTXO[]>;
27
+ listUnspent: (address: AddressOption, options?: UtxoQueryOptions) => Promise<UTXOWithHeight[]>;
25
28
  getBalance: (address: AddressOption) => Promise<{
26
29
  confirmed: number;
27
30
  unconfirmed: number;
@@ -43,14 +43,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
43
43
  };
44
44
  Object.defineProperty(exports, "__esModule", { value: true });
45
45
  exports.GNProvider = void 0;
46
- // Agrega esto al inicio del archivo
47
- // @ts-ignore
48
46
  const events_1 = require("events");
49
47
  const scryptlib = __importStar(require("scryptlib"));
50
48
  const abstract_provider_1 = require("scrypt-ts/dist/bsv/abstract-provider");
51
49
  const superagent = __importStar(require("superagent"));
52
- const utils_1 = require("scrypt-ts/dist/bsv/utils");
53
- //import { EventEmitter } from 'events';
54
50
  var ProviderEvent;
55
51
  (function (ProviderEvent) {
56
52
  ProviderEvent["Connected"] = "connected";
@@ -63,19 +59,11 @@ class GNProvider extends abstract_provider_1.Provider {
63
59
  this._getHeaders = () => {
64
60
  return Object.assign({ 'Content-Type': 'application/json' }, (this._apiKey ? { 'woc-api-key': this._apiKey } : {}));
65
61
  };
66
- /*get apiPrefix(): string {
67
- const networkStr = this._network.name === scryptlib.bsv.Networks.mainnet.name ? 'main' : 'test';
68
- return `https://api.whatsonchain.com/v1/bsv/${networkStr}`;
69
- }*/
70
- /*apiPrefix = (): string => {
71
- const networkStr = this._network.name === scryptlib.bsv.Networks.mainnet.name ? 'main' : 'test';
72
- return `https://api.whatsonchain.com/v1/bsv/${networkStr}`;
73
- }*/
74
62
  this.connect = () => __awaiter(this, void 0, void 0, function* () {
75
63
  var _a;
76
64
  try {
77
65
  const headers = this._getHeaders();
78
- const res = yield superagent.get(`${this.apiPrefix()}/woc`) //`${this.apiPrefix}/woc`)
66
+ const res = yield superagent.get(`${this.apiPrefix()}/woc`)
79
67
  .timeout(3000)
80
68
  .set(headers);
81
69
  if (res.ok && res.text === "Whats On Chain") {
@@ -91,60 +79,44 @@ class GNProvider extends abstract_provider_1.Provider {
91
79
  throw new Error(`connect failed: ${error.message || "unknown error"}`);
92
80
  }
93
81
  });
94
- //async getFeePerKb(): Promise<number> {
95
82
  this.getFeePerKb = () => __awaiter(this, void 0, void 0, function* () {
96
83
  yield this._ready();
97
84
  const headers = this._getHeaders();
98
85
  try {
99
- const now = Math.floor(Date.now() / 1000);
100
- const from = now - 1800; // 30 minutos atrás
101
- const res = yield superagent.get(`${this.apiPrefix()}/miner/fees?from=${from}&to=${now}`)
86
+ // Paso 1: Obtener la información de la cadena para obtener la altura actual
87
+ const chainInfoRes = yield superagent.get(`${this.apiPrefix()}/chain/info`)
88
+ .set(headers);
89
+ const currentHeight = chainInfoRes.body.blocks;
90
+ // Paso 2: Obtener las estadísticas del bloque actual
91
+ const blockStatsRes = yield superagent.get(`${this.apiPrefix()}/block/height/${currentHeight}/stats`)
102
92
  .set(headers);
103
- if (res.body && Array.isArray(res.body) && res.body.length > 0) {
104
- const totalFeeRate = res.body.reduce((sum, minerData) => {
105
- return sum + minerData.min_fee_rate;
106
- }, 0);
107
- const averageFeeRate = totalFeeRate / res.body.length;
108
- const feeRateWithMargin = averageFeeRate * 1.3;
109
- return Math.round(feeRateWithMargin * 100) / 100;
93
+ const blockStats = blockStatsRes.body;
94
+ const totalFee = blockStats.total_fee;
95
+ const size = blockStats.size;
96
+ // Si el tamaño es 0, evitar división por cero
97
+ if (size === 0) {
98
+ throw new Error('Block size is zero');
110
99
  }
111
- throw new Error("No fee data available");
100
+ // Calcular tarifa por kilobyte: (total_fee * 1024) / size
101
+ const feePerKb = (totalFee * 1024) / size;
102
+ // Aplicar un multiplicador para asegurar una tarifa competitiva (1.5x)
103
+ const competitiveFee = feePerKb * 1.5;
104
+ // Establecer un mínimo de 50 sat/kb y un máximo de 5000 sat/kb para evitar valores extremos
105
+ const safeFee = Math.max(50, Math.min(competitiveFee, 5000));
106
+ console.log(`Calculated fee rate: ${safeFee.toFixed(2)} sat/kb from block ${currentHeight}`);
107
+ return Math.round(safeFee * 100) / 100;
112
108
  }
113
109
  catch (error) {
114
- return 1.05; // Valor de fallback
110
+ console.warn('Fee estimation from block stats failed, using fallback');
111
+ return 500; // Fallback a 500 sat/kb
115
112
  }
116
113
  });
117
- /*isConnected(): boolean {
118
- return this._isConnected;
119
- }*/
120
114
  this.isConnected = () => this._isConnected;
121
- /*private _getHeaders() {
122
- return {
123
- 'Content-Type': 'application/json',
124
- ...(this._apiKey ? { 'woc-api-key': this._apiKey } : {})
125
- };
126
- }*/
127
- /*updateNetwork(network: scryptlib.bsv.Networks.Network): void {
128
- this._network = network;
129
- this.emit(ProviderEvent.NetworkChange, network);
130
- }*/
131
115
  this.updateNetwork = (network) => {
132
116
  this._network = network;
133
117
  this.emit(ProviderEvent.NetworkChange, network);
134
118
  };
135
- /*getNetwork(): scryptlib.bsv.Networks.Network {
136
- return this._network;
137
- }*/
138
119
  this.getNetwork = () => this._network;
139
- /*protected async _ready(): Promise<void> {
140
- if (!this.isConnected()) {
141
- try {
142
- await this.connect();
143
- } catch (error) {
144
- throw error;
145
- }
146
- }
147
- }*/
148
120
  this._ready = () => __awaiter(this, void 0, void 0, function* () {
149
121
  if (!this.isConnected()) {
150
122
  try {
@@ -155,13 +127,12 @@ class GNProvider extends abstract_provider_1.Provider {
155
127
  }
156
128
  }
157
129
  });
158
- //async sendRawTransaction(rawTxHex: string): Promise<TxHash> {
159
130
  this.sendRawTransaction = (rawTxHex) => __awaiter(this, void 0, void 0, function* () {
160
131
  var _a;
161
132
  yield this._ready();
162
133
  const headers = this._getHeaders();
163
- const size = Math.max(1, rawTxHex.length / 2 / 1024); // Tamaño en KB
164
- const timeout = Math.max(10000, 1000 * size); // Timeout dinámico
134
+ const size = Math.max(1, rawTxHex.length / 2 / 1024);
135
+ const timeout = Math.max(10000, 1000 * size);
165
136
  try {
166
137
  const res = yield superagent.post(`${this.apiPrefix()}/tx/raw`)
167
138
  .timeout({
@@ -182,14 +153,12 @@ class GNProvider extends abstract_provider_1.Provider {
182
153
  throw new Error(`GNProvider ERROR: ${error.message}`);
183
154
  }
184
155
  });
185
- // Implementación correcta de sendTransaction
186
156
  this.sendTransaction = (signedTx) => __awaiter(this, void 0, void 0, function* () {
187
157
  try {
188
158
  const txHex = signedTx.serialize({ disableIsFullySigned: true });
189
159
  return yield this.sendRawTransaction(txHex);
190
160
  }
191
161
  catch (error) {
192
- // Manejo seguro del error unknown
193
162
  let errorMessage = "Unknown error occurred";
194
163
  if (error instanceof Error) {
195
164
  errorMessage = error.message;
@@ -206,21 +175,20 @@ class GNProvider extends abstract_provider_1.Provider {
206
175
  throw new Error(`GNProvider ERROR: failed to send transaction: ${errorMessage}`);
207
176
  }
208
177
  });
209
- //async listUnspent(address: AddressOption, options?: UtxoQueryOptions): Promise<UTXO[]> {
210
178
  this.listUnspent = (address, options) => __awaiter(this, void 0, void 0, function* () {
211
179
  yield this._ready();
212
180
  const headers = this._getHeaders();
213
181
  const res = yield superagent.get(`${this.apiPrefix()}/address/${address}/unspent`)
214
182
  .set(headers);
215
- const utxos = res.body.map((item) => ({
183
+ return res.body.map((item) => ({
216
184
  txId: item.tx_hash,
217
185
  outputIndex: item.tx_pos,
218
186
  satoshis: item.value,
219
187
  script: scryptlib.bsv.Script.buildPublicKeyHashOut(address).toHex(),
188
+ height: item.height
220
189
  }));
221
- return options ? (0, utils_1.filterUTXO)(utxos, options) : utxos;
190
+ //return options ? filterUTXO(utxos, options) : utxos;
222
191
  });
223
- //async getBalance(address: AddressOption): Promise<{ confirmed: number; unconfirmed: number }> {
224
192
  this.getBalance = (address) => __awaiter(this, void 0, void 0, function* () {
225
193
  try {
226
194
  const headers = this._getHeaders();
@@ -240,7 +208,6 @@ class GNProvider extends abstract_provider_1.Provider {
240
208
  };
241
209
  }
242
210
  });
243
- //async getTransaction(txHash: string): Promise<TransactionResponse> {
244
211
  this.getTransaction = (txHash) => __awaiter(this, void 0, void 0, function* () {
245
212
  yield this._ready();
246
213
  const headers = this._getHeaders();
@@ -256,11 +223,6 @@ class GNProvider extends abstract_provider_1.Provider {
256
223
  throw new Error(`Error fetching transaction: ${error.message}`);
257
224
  }
258
225
  });
259
- /*private needIgnoreError(inMsg: string): boolean {
260
- if (inMsg.includes('Transaction already in the mempool')) return true;
261
- if (inMsg.includes('txn-already-known')) return true;
262
- return false;
263
- }*/
264
226
  this.needIgnoreError = (inMsg) => {
265
227
  if (inMsg.includes('Transaction already in the mempool'))
266
228
  return true;
@@ -268,7 +230,6 @@ class GNProvider extends abstract_provider_1.Provider {
268
230
  return true;
269
231
  return false;
270
232
  };
271
- //private friendlyBIP22RejectionMsg(inMsg: string): string {
272
233
  this.friendlyBIP22RejectionMsg = (inMsg) => {
273
234
  const messages = {
274
235
  'bad-txns-vin-empty': 'Transaction is missing inputs.',
@@ -290,7 +251,6 @@ class GNProvider extends abstract_provider_1.Provider {
290
251
  }
291
252
  return inMsg;
292
253
  };
293
- // Inicializa propiedades primero
294
254
  this._network = network;
295
255
  this._apiKey = apiKey;
296
256
  this._isConnected = false;
@@ -298,9 +258,7 @@ class GNProvider extends abstract_provider_1.Provider {
298
258
  const networkStr = this._network.name === scryptlib.bsv.Networks.mainnet.name ? 'main' : 'test';
299
259
  return `https://api.whatsonchain.com/v1/bsv/${networkStr}`;
300
260
  };
301
- // Configura EventEmitter
302
261
  Object.setPrototypeOf(this, events_1.EventEmitter.prototype);
303
- // Conexión directa
304
262
  this.connect().catch(console.error);
305
263
  }
306
264
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gn-provider",
3
- "version": "1.1.8",
3
+ "version": "1.2.0",
4
4
  "files": [
5
5
  "dist",
6
6
  "scripts",