gn-provider 1.2.4 → 1.2.6

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.
@@ -9,12 +9,14 @@ export declare class GNProvider extends Provider {
9
9
  emit: (event: ProviderEvent, ...args: any[]) => boolean;
10
10
  private _network;
11
11
  private _isConnected;
12
- private _apiKey;
12
+ private _wocApiKey;
13
+ private _gorillaPoolApiKey;
13
14
  private apiPrefix;
15
+ private _mapiURL;
14
16
  private _getHeaders;
15
17
  connect: () => Promise<this>;
16
18
  getFeePerKb: () => Promise<number>;
17
- constructor(network: scryptlib.bsv.Networks.Network, apiKey?: string);
19
+ constructor(network: scryptlib.bsv.Networks.Network, wocApiKey?: string, gpApiKey?: string);
18
20
  isConnected: () => boolean;
19
21
  updateNetwork: (network: scryptlib.bsv.Networks.Network) => void;
20
22
  getNetwork: () => scryptlib.bsv.Networks.Network;
@@ -57,11 +57,11 @@ var ProviderEvent;
57
57
  height: number;
58
58
  };*/
59
59
  class GNProvider extends abstract_provider_1.Provider {
60
- constructor(network, apiKey = '') {
60
+ constructor(network, wocApiKey = '', gpApiKey = '') {
61
61
  super();
62
62
  this._isConnected = false;
63
63
  this._getHeaders = () => {
64
- return Object.assign({ 'Content-Type': 'application/json' }, (this._apiKey ? { 'woc-api-key': this._apiKey } : {}));
64
+ return Object.assign({ 'Content-Type': 'application/json' }, (this._wocApiKey ? { 'woc-api-key': this._wocApiKey } : {}));
65
65
  };
66
66
  this.connect = () => __awaiter(this, void 0, void 0, function* () {
67
67
  var _a;
@@ -131,6 +131,100 @@ class GNProvider extends abstract_provider_1.Provider {
131
131
  }
132
132
  }
133
133
  });
134
+ /*sendRawTransaction = async (rawTxHex: string): Promise<TxHash> => {
135
+ await this._ready();
136
+ const headers = this._getHeaders();
137
+ const size = Math.max(1, rawTxHex.length / 2 / 1024);
138
+ const timeout = Math.max(10000, 1000 * size);
139
+
140
+ try {
141
+ const res = await superagent.post(`${this.apiPrefix()}/tx/raw`)
142
+ .timeout({
143
+ response: timeout,
144
+ deadline: 60000
145
+ })
146
+ .set(headers)
147
+ .send({ txhex: rawTxHex });
148
+
149
+ return res.body;
150
+ } catch (error: any) {
151
+ if (error.response?.text) {
152
+ if (this.needIgnoreError(error.response.text)) {
153
+ return new scryptlib.bsv.Transaction(rawTxHex).id;
154
+ }
155
+ throw new Error(`GNProvider ERROR: ${this.friendlyBIP22RejectionMsg(error.response.text)}`);
156
+ }
157
+ throw new Error(`GNProvider ERROR: ${error.message}`);
158
+ }
159
+ }*/
160
+ /*sendRawTransaction = async (rawTxHex: string): Promise<TxHash> => {
161
+ await this._ready();
162
+ const headers = this._getHeaders();
163
+ const size = Math.max(1, rawTxHex.length / 2 / 1024);
164
+ const timeout = Math.max(15000, 1000 * size);
165
+
166
+ // 1. Preparar el envío a WhatsOnChain (tu implementación actual)
167
+ const wocRequest = superagent.post(`${this.apiPrefix()}/tx/raw`)
168
+ .timeout({
169
+ response: timeout,
170
+ deadline: 60000
171
+ })
172
+ .set(headers)
173
+ .send({ txhex: rawTxHex });
174
+
175
+ // 2. Preparar el envío a GorillaPool (basado en el código de referencia)
176
+ const gpRequest = superagent.post(this._mapiURL + 'tx')
177
+ .timeout({
178
+ response: timeout,
179
+ deadline: 60000,
180
+ })
181
+ .set('Content-Type', 'application/octet-stream')
182
+ .send(Buffer.from(rawTxHex, 'hex'));
183
+
184
+ if (this._gorillaPoolApiKey) {
185
+ gpRequest.set('Authorization', `Bearer ${this._gorillaPoolApiKey}`);
186
+ }
187
+
188
+ // 3. Ejecutar ambos envíos en paralelo y obtener el primer resultado exitoso
189
+ try {
190
+ const responses = await Promise.allSettled([
191
+ wocRequest.then(res => ({ source: 'WhatsOnChain', result: res.body })),
192
+ gpRequest.then(res => {
193
+ const payload = JSON.parse(res.body.payload);
194
+ if (payload.returnResult === 'success') {
195
+ return { source: 'GorillaPool', result: payload.txid };
196
+ } else {
197
+ throw new Error(`GorillaPool: ${payload.resultDescription}`);
198
+ }
199
+ })
200
+ ]);
201
+
202
+ // Buscar el primer resultado exitoso
203
+ for (const response of responses) {
204
+ if (response.status === 'fulfilled') {
205
+ console.log(`✅ Transacción aceptada por: ${response.value.source}`);
206
+ return response.value.result; // Retorna el TXID
207
+ }
208
+ }
209
+
210
+ // Si ambos fallan, lanza el primer error
211
+ const firstRejection = responses.find(r => r.status === 'rejected');
212
+ if (firstRejection) {
213
+ throw new Error(firstRejection.reason.message || firstRejection.reason);
214
+ }
215
+
216
+ throw new Error('Todos los intentos de envío fallaron');
217
+
218
+ } catch (error: any) {
219
+ if (error.response?.text) {
220
+ if (this.needIgnoreError(error.response.text)) {
221
+ return new scryptlib.bsv.Transaction(rawTxHex).id;
222
+ }
223
+ throw new Error(`GNProvider ERROR: ${this.friendlyBIP22RejectionMsg(error.response.text)}`);
224
+ }
225
+ throw new Error(`GNProvider ERROR: ${error.message}`);
226
+ }
227
+ }*/
134
228
  this.sendRawTransaction = (rawTxHex) => __awaiter(this, void 0, void 0, function* () {
135
229
  var _a;
136
230
  yield this._ready();
@@ -157,6 +251,73 @@ class GNProvider extends abstract_provider_1.Provider {
157
251
  throw new Error(`GNProvider ERROR: ${error.message}`);
158
252
  }
159
253
  });
254
+ /*sendRawTransaction = async (rawTxHex: string): Promise<TxHash> => {
255
+ await this._ready();
256
+ const headers = this._getHeaders();
257
+ const size = Math.max(1, rawTxHex.length / 2 / 1024);
258
+ const timeout = Math.max(15000, 1000 * size);
259
+
260
+ const wocRequest = superagent.post(`${this.apiPrefix()}/tx/raw`)
261
+ .timeout({ response: timeout, deadline: 60000 })
262
+ .set(headers)
263
+ .send({ txhex: rawTxHex });
264
+
265
+ const gpRequest = superagent.post(this._mapiURL + 'tx')
266
+ .timeout({ response: timeout, deadline: 60000 })
267
+ .set('Content-Type', 'application/octet-stream')
268
+ .send(Buffer.from(rawTxHex, 'hex'));
269
+
270
+ if (this._gorillaPoolApiKey) {
271
+ gpRequest.set('Authorization', `Bearer ${this._gorillaPoolApiKey}`);
272
+ }
273
+
274
+ try {
275
+ const responses = await Promise.allSettled([
276
+ wocRequest.then(res => ({ source: 'WhatsOnChain', result: res.body })),
277
+ gpRequest.then(res => {
278
+ try {
279
+ if (!res.body?.payload) {
280
+ throw new Error('Respuesta inválida de GorillaPool: falta payload');
281
+ }
282
+
283
+ const payload = JSON.parse(res.body.payload);
284
+
285
+ if (payload.returnResult === 'success') {
286
+ return { source: 'GorillaPool', result: payload.txid };
287
+ } else {
288
+ throw new Error(`GorillaPool [${payload.returnResult || 'unknown'}]: ${payload.resultDescription || 'Sin descripción'}`);
289
+ }
290
+ } catch (parseError) {
291
+ const message = parseError instanceof Error ? parseError.message : String(parseError);
292
+ throw new Error(`GorillaPool: Error parsing response - ${message}`);
293
+ }
294
+ })
295
+ ]);
296
+
297
+ for (const response of responses) {
298
+ if (response.status === 'fulfilled') {
299
+ console.log(`✅ Transacción aceptada por: ${response.value.source}`);
300
+ return response.value.result;
301
+ }
302
+ }
303
+
304
+ const firstRejection = responses.find(r => r.status === 'rejected');
305
+ if (firstRejection) {
306
+ throw new Error(firstRejection.reason.message || firstRejection.reason);
307
+ }
308
+
309
+ throw new Error('Todos los intentos de envío fallaron');
310
+
311
+ } catch (error: any) {
312
+ if (error.response?.text) {
313
+ if (this.needIgnoreError(error.response.text)) {
314
+ return new scryptlib.bsv.Transaction(rawTxHex).id;
315
+ }
316
+ throw new Error(`GNProvider ERROR: ${this.friendlyBIP22RejectionMsg(error.response.text)}`);
317
+ }
318
+ throw new Error(`GNProvider ERROR: ${error.message}`);
319
+ }
320
+ }*/
160
321
  this.sendTransaction = (signedTx) => __awaiter(this, void 0, void 0, function* () {
161
322
  try {
162
323
  const txHex = signedTx.serialize({ disableIsFullySigned: true });
@@ -267,8 +428,12 @@ class GNProvider extends abstract_provider_1.Provider {
267
428
  return inMsg;
268
429
  };
269
430
  this._network = network;
270
- this._apiKey = apiKey;
431
+ this._wocApiKey = wocApiKey;
432
+ this._gorillaPoolApiKey = gpApiKey;
271
433
  this._isConnected = false;
434
+ this._mapiURL = network == scryptlib.bsv.Networks.mainnet ?
435
+ 'https://mapi.gorillapool.io/mapi/' :
436
+ 'https://testnet-mapi.gorillapool.io/mapi/';
272
437
  this.apiPrefix = () => {
273
438
  const networkStr = this._network.name === scryptlib.bsv.Networks.mainnet.name ? 'main' : 'test';
274
439
  return `https://api.whatsonchain.com/v1/bsv/${networkStr}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gn-provider",
3
- "version": "1.2.4",
3
+ "version": "1.2.6",
4
4
  "files": [
5
5
  "dist",
6
6
  "scripts",