gn-provider 1.2.3 → 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.
- package/dist/gn-provider.d.ts +4 -2
- package/dist/gn-provider.js +145 -11
- package/package.json +1 -1
package/dist/gn-provider.d.ts
CHANGED
|
@@ -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
|
|
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,
|
|
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;
|
package/dist/gn-provider.js
CHANGED
|
@@ -57,11 +57,11 @@ var ProviderEvent;
|
|
|
57
57
|
height: number;
|
|
58
58
|
};*/
|
|
59
59
|
class GNProvider extends abstract_provider_1.Provider {
|
|
60
|
-
constructor(network,
|
|
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.
|
|
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
|
-
|
|
135
|
-
|
|
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 =
|
|
141
|
+
const res = await superagent.post(`${this.apiPrefix()}/tx/raw`)
|
|
142
142
|
.timeout({
|
|
143
|
-
|
|
144
|
-
|
|
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) {
|
|
@@ -189,7 +319,7 @@ class GNProvider extends abstract_provider_1.Provider {
|
|
|
189
319
|
txId: item.tx_hash,
|
|
190
320
|
outputIndex: item.tx_pos,
|
|
191
321
|
satoshis: item.value,
|
|
192
|
-
script: item.script, // ✅ CORRECTO - script real de la blockchain //
|
|
322
|
+
script: scryptlib.bsv.Script.buildPublicKeyHashOut(address).toHex(), //item.script, // ✅ CORRECTO - script real de la blockchain //
|
|
193
323
|
}));
|
|
194
324
|
return options ? (0, utils_1.filterUTXO)(utxos, options) : utxos;
|
|
195
325
|
}
|
|
@@ -267,8 +397,12 @@ class GNProvider extends abstract_provider_1.Provider {
|
|
|
267
397
|
return inMsg;
|
|
268
398
|
};
|
|
269
399
|
this._network = network;
|
|
270
|
-
this.
|
|
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}`;
|