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.
- package/dist/gn-provider.d.ts +4 -1
- package/dist/gn-provider.js +28 -70
- package/package.json +1 -1
package/dist/gn-provider.d.ts
CHANGED
|
@@ -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<
|
|
27
|
+
listUnspent: (address: AddressOption, options?: UtxoQueryOptions) => Promise<UTXOWithHeight[]>;
|
|
25
28
|
getBalance: (address: AddressOption) => Promise<{
|
|
26
29
|
confirmed: number;
|
|
27
30
|
unconfirmed: number;
|
package/dist/gn-provider.js
CHANGED
|
@@ -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`)
|
|
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
|
-
|
|
100
|
-
const
|
|
101
|
-
|
|
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
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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);
|
|
164
|
-
const timeout = Math.max(10000, 1000 * size);
|
|
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
|
-
|
|
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 ?
|
|
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
|
}
|