gn-provider 1.2.4 → 1.2.5

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,21 +131,151 @@ class GNProvider extends abstract_provider_1.Provider {
131
131
  }
132
132
  }
133
133
  });
134
- this.sendRawTransaction = (rawTxHex) => __awaiter(this, void 0, void 0, function* () {
135
- var _a;
136
- yield this._ready();
134
+ /*sendRawTransaction = async (rawTxHex: string): Promise<TxHash> => {
135
+ await this._ready();
137
136
  const headers = this._getHeaders();
138
137
  const size = Math.max(1, rawTxHex.length / 2 / 1024);
139
138
  const timeout = Math.max(10000, 1000 * size);
139
+
140
140
  try {
141
- const res = yield superagent.post(`${this.apiPrefix()}/tx/raw`)
141
+ const res = await superagent.post(`${this.apiPrefix()}/tx/raw`)
142
142
  .timeout({
143
- response: timeout,
144
- deadline: 60000
145
- })
143
+ response: timeout,
144
+ deadline: 60000
145
+ })
146
146
  .set(headers)
147
147
  .send({ txhex: rawTxHex });
148
+
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
+ }*/
228
+ this.sendRawTransaction = (rawTxHex) => __awaiter(this, void 0, void 0, function* () {
229
+ var _a;
230
+ yield this._ready();
231
+ const headers = this._getHeaders();
232
+ const size = Math.max(1, rawTxHex.length / 2 / 1024);
233
+ const timeout = Math.max(15000, 1000 * size);
234
+ const wocRequest = superagent.post(`${this.apiPrefix()}/tx/raw`)
235
+ .timeout({ response: timeout, deadline: 60000 })
236
+ .set(headers)
237
+ .send({ txhex: rawTxHex });
238
+ const gpRequest = superagent.post(this._mapiURL + 'tx')
239
+ .timeout({ response: timeout, deadline: 60000 })
240
+ .set('Content-Type', 'application/octet-stream')
241
+ .send(Buffer.from(rawTxHex, 'hex'));
242
+ if (this._gorillaPoolApiKey) {
243
+ gpRequest.set('Authorization', `Bearer ${this._gorillaPoolApiKey}`);
244
+ }
245
+ try {
246
+ const responses = yield Promise.allSettled([
247
+ wocRequest.then(res => ({ source: 'WhatsOnChain', result: res.body })),
248
+ gpRequest.then(res => {
249
+ var _a;
250
+ try {
251
+ if (!((_a = res.body) === null || _a === void 0 ? void 0 : _a.payload)) {
252
+ throw new Error('Respuesta inválida de GorillaPool: falta payload');
253
+ }
254
+ const payload = JSON.parse(res.body.payload);
255
+ if (payload.returnResult === 'success') {
256
+ return { source: 'GorillaPool', result: payload.txid };
257
+ }
258
+ else {
259
+ throw new Error(`GorillaPool [${payload.returnResult || 'unknown'}]: ${payload.resultDescription || 'Sin descripción'}`);
260
+ }
261
+ }
262
+ catch (parseError) {
263
+ const message = parseError instanceof Error ? parseError.message : String(parseError);
264
+ throw new Error(`GorillaPool: Error parsing response - ${message}`);
265
+ }
266
+ })
267
+ ]);
268
+ for (const response of responses) {
269
+ if (response.status === 'fulfilled') {
270
+ console.log(`✅ Transacción aceptada por: ${response.value.source}`);
271
+ return response.value.result;
272
+ }
273
+ }
274
+ const firstRejection = responses.find(r => r.status === 'rejected');
275
+ if (firstRejection) {
276
+ throw new Error(firstRejection.reason.message || firstRejection.reason);
277
+ }
278
+ throw new Error('Todos los intentos de envío fallaron');
149
279
  }
150
280
  catch (error) {
151
281
  if ((_a = error.response) === null || _a === void 0 ? void 0 : _a.text) {
@@ -267,8 +397,12 @@ class GNProvider extends abstract_provider_1.Provider {
267
397
  return inMsg;
268
398
  };
269
399
  this._network = network;
270
- this._apiKey = apiKey;
400
+ this._wocApiKey = wocApiKey;
401
+ this._gorillaPoolApiKey = gpApiKey;
271
402
  this._isConnected = false;
403
+ this._mapiURL = network == scryptlib.bsv.Networks.mainnet ?
404
+ 'https://mapi.gorillapool.io/mapi/' :
405
+ 'https://testnet-mapi.gorillapool.io/mapi/';
272
406
  this.apiPrefix = () => {
273
407
  const networkStr = this._network.name === scryptlib.bsv.Networks.mainnet.name ? 'main' : 'test';
274
408
  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.5",
4
4
  "files": [
5
5
  "dist",
6
6
  "scripts",