@ar.io/wayfinder-core 0.0.3-alpha.6 → 0.0.4-alpha.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/README.md CHANGED
@@ -49,15 +49,48 @@ const wayfinder = new Wayfinder({
49
49
  limit: 10,
50
50
  }),
51
51
  }),
52
- // use the fastest pinging strategy to select the fastest gateway for requests
53
- routingStrategy: new FastestPingRoutingStrategy({
54
- timeoutMs: 1000,
55
- probePath: '/ar-io/info',
56
- }),
57
- // verify the data using the hash of the data against a list of trusted gateways
58
- verificationStrategy: new HashVerificationStrategy({
59
- trustedGateways: ['https://permagate.io'],
60
- }),
52
+ // routing settings
53
+ routingSettings: {
54
+ // use the fastest pinging strategy to select the fastest gateway for requests
55
+ strategy: new FastestPingRoutingStrategy({
56
+ timeoutMs: 1000,
57
+ }),
58
+ // events
59
+ events: {
60
+ onRoutingStarted: (event) => {
61
+ console.log('Routing started!', event);
62
+ },
63
+ onRoutingSkipped: (event) => {
64
+ console.log('Routing skipped!', event);
65
+ },
66
+ onRoutingSucceeded: (event) => {
67
+ console.log('Routing succeeded!', event);
68
+ },
69
+ },
70
+ },
71
+ // verification settings
72
+ verificationSettings: {
73
+ // enable verification - if false, verification will be skipped for all requests
74
+ enabled: true,
75
+ // verify the data using the hash of the data against a list of trusted gateways
76
+ strategy: new HashVerificationStrategy({
77
+ trustedGateways: ['https://permagate.io'],
78
+ }),
79
+ // strict verification - if true, verification failures will cause requests to fail
80
+ strict: true,
81
+ // events
82
+ events: {
83
+ onVerificationProgress: (event) => {
84
+ console.log('Verification progress!', event);
85
+ },
86
+ onVerificationSucceeded: (event) => {
87
+ console.log('Verification succeeded!', event);
88
+ },
89
+ onVerificationFailed: (event) => {
90
+ console.log('Verification failed!', event);
91
+ },
92
+ },
93
+ },
61
94
  });
62
95
  ```
63
96
 
@@ -125,6 +158,8 @@ const gateway = await routingStrategy.selectGateway({
125
158
  ### StaticRoutingStrategy
126
159
 
127
160
  ```javascript
161
+ import { Wayfinder, StaticRoutingStrategy } from '@ar.io/wayfinder-core';
162
+
128
163
  const routingStrategy = new StaticRoutingStrategy({
129
164
  gateway: 'https://arweave.net',
130
165
  });
@@ -137,6 +172,9 @@ const gateway = await routingStrategy.selectGateway(); // always returns the sam
137
172
  Selects gateways in round-robin order. The gateway list is stored in memory and is not persisted across instances.
138
173
 
139
174
  ```javascript
175
+ import { Wayfinder, NetworkGatewaysProvider, RoundRobinRoutingStrategy } from '@ar.io/wayfinder-core';
176
+ import { ARIO } from '@ar.io/sdk';
177
+
140
178
  const gatewayProvider = new NetworkGatewaysProvider({
141
179
  ario: ARIO.mainnet(),
142
180
  sortBy: 'operatorStake',
@@ -158,6 +196,8 @@ const gateway = await routingStrategy.selectGateway(); // returns the next gatew
158
196
  Selects the fastest gateway based simple HEAD request to the specified route.
159
197
 
160
198
  ```javascript
199
+ import { Wayfinder, FastestPingRoutingStrategy } from '@ar.io/wayfinder-core';
200
+
161
201
  const routingStrategy = new FastestPingRoutingStrategy({
162
202
  timeoutMs: 1000,
163
203
  });
@@ -186,9 +226,11 @@ Verifies data integrity using SHA-256 hash comparison. This is the default verif
186
226
  import { Wayfinder, HashVerificationStrategy } from '@ar.io/wayfinder-core';
187
227
 
188
228
  const wayfinder = new Wayfinder({
189
- verificationStrategy: new HashVerificationStrategy({
190
- trustedGateways: ['https://permagate.io'],
191
- }),
229
+ verificationSettings: {
230
+ strategy: new HashVerificationStrategy({
231
+ trustedGateways: ['https://permagate.io'],
232
+ }),
233
+ },
192
234
  });
193
235
  ```
194
236
 
@@ -200,9 +242,11 @@ Verifies data integrity using Arweave by computing the data root for the transac
200
242
  import { Wayfinder, DataRootVerificationStrategy } from '@ar.io/wayfinder-core';
201
243
 
202
244
  const wayfinder = new Wayfinder({
203
- verificationStrategy: new DataRootVerificationStrategy({
204
- trustedGateways: ['https://permagate.io'],
205
- }),
245
+ verificationSettings: {
246
+ strategy: new DataRootVerificationStrategy({
247
+ trustedGateways: ['https://permagate.io'],
248
+ }),
249
+ },
206
250
  });
207
251
  ```
208
252
 
@@ -214,33 +258,50 @@ Verifies signatures of Arweave transactions and data items. Headers are retrieve
214
258
  import { Wayfinder, SignatureVerificationStrategy } from '@ar-io/sdk';
215
259
 
216
260
  const wayfinder = new Wayfinder({
217
- verificationStrategy: new SignatureVerificationStrategy({
218
- trustedGateways: ['https://permagate.io'],
219
- }),
261
+ verificationSettings: {
262
+ strategy: new SignatureVerificationStrategy({
263
+ trustedGateways: ['https://permagate.io'],
264
+ }),
265
+ },
220
266
  });
221
267
  ```
222
268
 
223
269
  ## Monitoring and Events
224
270
 
225
- Wayfinder emits events during the routing and verification process, allowing you to monitor its operation.
271
+ Wayfinder emits events during the routing and verification process, allowing you to monitor its operation. You can provide these events to the Wayfinder constructor or use the event emitter directly.
226
272
 
227
273
  ```javascript
228
274
  const wayfinder = new Wayfinder({
229
- events: {
230
- onVerificationPassed: (event) => {
231
- console.log(`Verification passed for transaction: ${event.txId}`);
232
- },
233
- onVerificationFailed: (event) => {
234
- console.error(
235
- `Verification failed for transaction: ${event.txId}`,
236
- event.error,
237
- );
275
+ routingSettings: {
276
+ events: {
277
+ onRoutingStarted: (event) => {
278
+ console.log('Routing started!', event);
279
+ },
280
+ onRoutingSkipped: (event) => {
281
+ console.log('Routing skipped!', event);
282
+ },
283
+ onRoutingSucceeded: (event) => {
284
+ console.log('Routing succeeded!', event);
285
+ },
238
286
  },
239
- onVerificationProgress: (event) => {
240
- const percentage = (event.processedBytes / event.totalBytes) * 100;
241
- console.log(
242
- `Verification progress for ${event.txId}: ${percentage.toFixed(2)}%`,
243
- );
287
+ },
288
+ verificationSettings: {
289
+ events: {
290
+ onVerificationSucceeded: (event) => {
291
+ console.log(`Verification passed for transaction: ${event.txId}`);
292
+ },
293
+ onVerificationFailed: (event) => {
294
+ console.error(
295
+ `Verification failed for transaction: ${event.txId}`,
296
+ event.error,
297
+ );
298
+ },
299
+ onVerificationProgress: (event) => {
300
+ const percentage = (event.processedBytes / event.totalBytes) * 100;
301
+ console.log(
302
+ `Verification progress for ${event.txId}: ${percentage.toFixed(2)}%`,
303
+ );
304
+ },
244
305
  },
245
306
  },
246
307
  });
@@ -253,12 +314,26 @@ wayfinder.emitter.on('routing-succeeded', (event) => {
253
314
  wayfinder.emitter.on('routing-failed', (event) => {
254
315
  console.error(`Routing failed: ${event.error.message}`);
255
316
  });
317
+
318
+ wayfinder.emitter.on('verification-progress', (event) => {
319
+ console.log(`Verification progress: ${event.progress}%`);
320
+ });
321
+
322
+ wayfinder.emitter.on('verification-succeeded', (event) => {
323
+ console.log(`Verification succeeded: ${event.txId}`);
324
+ });
325
+
326
+ wayfinder.emitter.on('verification-failed', (event) => {
327
+ console.error(`Verification failed: ${event.error.message}`);
328
+ });
256
329
  ```
257
330
 
258
331
  ## Advanced Usage
259
332
 
260
333
  ### Custom URL Resolution
261
334
 
335
+ Returns the resolved URL for a given ar:// URL. This is useful for debugging and for users who want to know the target gateway for a given ar:// URL.
336
+
262
337
  ```javascript
263
338
  // Get the resolved URL without making a request
264
339
  const redirectUrl = await wayfinder.resolveUrl({
@@ -267,27 +342,6 @@ const redirectUrl = await wayfinder.resolveUrl({
267
342
  console.log(`This request would be routed to: ${redirectUrl}`);
268
343
  ```
269
344
 
270
- ### Using With Different HTTP Clients
271
-
272
- By default, Wayfinder uses native `fetch` for HTTP requests. You can also use other HTTP clients like `axios` or `node-fetch`. When making a request, Wayfinder will use the HTTP client you provide and any additional configuration you provide.
273
-
274
- ```javascript
275
- import axios from 'axios';
276
-
277
- // create a custom axios instance
278
- const axios = axios.create({
279
- timeout: 10000,
280
- });
281
- const wayfinderAxios = new Wayfinder({ httpClient: axios });
282
-
283
- // add custom headers on the request
284
- const response = await wayfinderAxios.request('ar://example', {
285
- headers: {
286
- 'X-Custom-Header': 'test',
287
- },
288
- });
289
- ```
290
-
291
345
  ## Request Flow
292
346
 
293
347
  The following sequence diagram illustrates how Wayfinder processes requests:
@@ -14,7 +14,7 @@
14
14
  * See the License for the specific language governing permissions and
15
15
  * limitations under the License.
16
16
  */
17
- import * as crypto from 'crypto';
17
+ import { createHash } from 'crypto';
18
18
  import { defaultLogger } from '../wayfinder.js';
19
19
  import { toB64Url } from './base64.js';
20
20
  export function isAsyncIterable(obj) {
@@ -48,7 +48,7 @@ export async function hashDataStreamToB64Url({ stream, algorithm = 'sha256', log
48
48
  const asyncIterable = isAsyncIterable(stream)
49
49
  ? stream
50
50
  : readableStreamToAsyncIterable(stream);
51
- const hash = crypto.createHash(algorithm);
51
+ const hash = createHash(algorithm);
52
52
  let bytesProcessed = 0;
53
53
  for await (const chunk of asyncIterable) {
54
54
  hash.update(chunk);
@@ -78,13 +78,22 @@ export type WayfinderEvent = {
78
78
  txId: string;
79
79
  };
80
80
  };
81
- export interface WayfinderEventArgs {
81
+ export interface WayfinderRoutingEventArgs {
82
+ onRoutingStarted?: (payload: WayfinderEvent['routing-started']) => void;
83
+ onRoutingSkipped?: (payload: WayfinderEvent['routing-skipped']) => void;
84
+ onRoutingSucceeded?: (payload: WayfinderEvent['routing-succeeded']) => void;
85
+ }
86
+ export interface WayfinderVerificationEventArgs {
82
87
  onVerificationSucceeded?: (payload: WayfinderEvent['verification-succeeded']) => void;
83
88
  onVerificationFailed?: (payload: WayfinderEvent['verification-failed']) => void;
84
89
  onVerificationProgress?: (payload: WayfinderEvent['verification-progress']) => void;
85
90
  }
91
+ export interface WayfinderEventArgs {
92
+ verification?: WayfinderVerificationEventArgs;
93
+ routing?: WayfinderRoutingEventArgs;
94
+ }
86
95
  export declare class WayfinderEmitter extends EventEmitter<WayfinderEvent> {
87
- constructor({ onVerificationSucceeded, onVerificationFailed, onVerificationProgress, }?: WayfinderEventArgs);
96
+ constructor({ verification, routing }?: WayfinderEventArgs);
88
97
  }
89
98
  export declare function tapAndVerifyReadableStream({ originalStream, contentLength, verifyData, txId, emitter, strict, }: {
90
99
  originalStream: ReadableStream;
@@ -109,7 +118,7 @@ export declare function sandboxFromId(id: string): string;
109
118
  * @param resolveUrl - the function to construct the redirect url for ar:// requests
110
119
  * @returns a wrapped fetch function that supports ar:// protocol and always returns Response
111
120
  */
112
- export declare const createWayfinderClient: ({ getGateways, resolveUrl, verifyData, selectGateway, emitter, logger, strict, }: {
121
+ export declare const wayfinderRequest: ({ getGateways, resolveUrl, verifyData, selectGateway, emitter, logger, strict, }: {
113
122
  getGateways: GatewaysProvider["getGateways"];
114
123
  selectGateway: RoutingStrategy["selectGateway"];
115
124
  resolveUrl: (params: {
@@ -132,30 +141,47 @@ export interface WayfinderOptions {
132
141
  */
133
142
  logger?: Logger;
134
143
  /**
135
- * The gateways provider to use for routing requests
144
+ * The gateways provider to use for routing requests.
136
145
  */
137
146
  gatewaysProvider: GatewaysProvider;
138
147
  /**
139
- * The routing strategy to use for selecting gateways
140
- * @default FastestPingRoutingStrategy with timeoutMs=1000
141
- */
142
- routingStrategy?: RoutingStrategy;
143
- /**
144
- * The verification strategy to use for verifying data
145
- * @default HashVerificationStrategy with TrustedGatewaysHashProvider
148
+ * The verification settings to use for verifying data
146
149
  */
147
- verificationStrategy?: VerificationStrategy;
148
- /**
149
- * Event handlers for verification events
150
- */
151
- events?: WayfinderEventArgs;
150
+ verificationSettings?: {
151
+ /**
152
+ * Whether verification is enabled. If false, verification will be skipped for all requests.
153
+ * @default true
154
+ */
155
+ enabled?: boolean;
156
+ /**
157
+ * Whether verification should be strict (blocking)
158
+ * If true, verification failures will cause requests to fail
159
+ * If false, verification will be performed asynchronously with events emitted
160
+ * @default false
161
+ */
162
+ strict?: boolean;
163
+ /**
164
+ * The events to use for verification
165
+ */
166
+ events?: WayfinderVerificationEventArgs;
167
+ /**
168
+ * The verification strategy to use for verifying data
169
+ */
170
+ strategy?: VerificationStrategy;
171
+ };
152
172
  /**
153
- * Whether verification should be strict (blocking)
154
- * If true, verification failures will cause requests to fail
155
- * If false, verification will be performed asynchronously
156
- * @default false
173
+ * The routing settings to use for routing requests
157
174
  */
158
- strict?: boolean;
175
+ routingSettings?: {
176
+ /**
177
+ * The routing strategy to use for routing requests
178
+ */
179
+ strategy?: RoutingStrategy;
180
+ /**
181
+ * The events to use for routing requests
182
+ */
183
+ events?: WayfinderRoutingEventArgs;
184
+ };
159
185
  }
160
186
  /**
161
187
  * The main class for the wayfinder
@@ -175,15 +201,12 @@ export declare class Wayfinder {
175
201
  readonly gatewaysProvider: GatewaysProvider;
176
202
  /**
177
203
  * The routing strategy to use when routing requests.
178
- *
179
- * @example
180
- * const wayfinder = new Wayfinder({
181
- * strategy: new FastestPingStrategy({
182
- * timeoutMs: 1000,
183
- * }),
184
- * });
185
204
  */
186
205
  readonly routingStrategy: RoutingStrategy;
206
+ /**
207
+ * The verification strategy to use when verifying data.
208
+ */
209
+ readonly verificationStrategy: VerificationStrategy;
187
210
  /**
188
211
  * A helper function that resolves the redirect url for ar:// requests to a target gateway.
189
212
  *
@@ -245,18 +268,12 @@ export declare class Wayfinder {
245
268
  * });
246
269
  */
247
270
  readonly verifyData: VerificationStrategy['verifyData'];
248
- /**
249
- * Whether verification should be strict (blocking) or not.
250
- * If true, verification failures will cause requests to fail.
251
- * If false, verification will be performed asynchronously and failures will only emit events.
252
- */
253
- readonly strict: boolean;
254
271
  /**
255
272
  * The logger used by this Wayfinder instance
256
273
  */
257
274
  readonly logger: Logger;
258
275
  /**
259
- * The event emitter for wayfinder that emits verification events.
276
+ * The event emitter for wayfinder that emits routing and verification events.
260
277
  *
261
278
  * const wayfinder = new Wayfinder()
262
279
  *
@@ -271,17 +288,40 @@ export declare class Wayfinder {
271
288
  * or implement the events interface and pass it in, using callback functions
272
289
  *
273
290
  * const wayfinder = new Wayfinder({
274
- * events: {
275
- * onVerificationPassed: (event) => {
276
- * console.log('Verification passed!', event);
277
- * },
278
- * onVerificationFailed: (event) => {
291
+ * verificationSettings: {
292
+ * strategy: new HashVerificationStrategy({
293
+ * trustedGateways: [new URL('https://permagate.io')],
294
+ * }),
295
+ * events: {
296
+ * onVerificationProgress: (event) => {
297
+ * console.log('Verification progress!', event);
298
+ * },
299
+ * onVerificationSucceeded: (event) => {
300
+ * console.log('Verification passed!', event);
301
+ * },
302
+ * onVerificationFailed: (event) => {
279
303
  * console.log('Verification failed!', event);
280
304
  * },
281
305
  * onVerificationProgress: (event) => {
282
306
  * console.log('Verification progress!', event);
283
307
  * },
284
308
  * }
309
+ * routingSettings: {
310
+ * strategy: new FastestPingRoutingStrategy({
311
+ * timeoutMs: 1000,
312
+ * }),
313
+ * events: {
314
+ * onRoutingStarted: (event) => {
315
+ * console.log('Routing started!', event);
316
+ * },
317
+ * onRoutingSkipped: (event) => {
318
+ * console.log('Routing skipped!', event);
319
+ * },
320
+ * onRoutingSucceeded: (event) => {
321
+ * console.log('Routing succeeded!', event);
322
+ * },
323
+ * },
324
+ * }
285
325
  * })
286
326
  *
287
327
  * const response = await wayfinder.request('ar://example');
@@ -291,7 +331,7 @@ export declare class Wayfinder {
291
331
  * The constructor for the wayfinder
292
332
  * @param options - Wayfinder configuration options
293
333
  */
294
- constructor({ logger, gatewaysProvider, routingStrategy, verificationStrategy, events, strict, }: WayfinderOptions);
334
+ constructor({ logger, gatewaysProvider, verificationSettings, routingSettings, }: WayfinderOptions);
295
335
  }
296
336
  export {};
297
337
  //# sourceMappingURL=wayfinder.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"wayfinder.d.ts","sourceRoot":"","sources":["../src/wayfinder.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"wayfinder.d.ts","sourceRoot":"","sources":["../src/wayfinder.ts"],"names":[],"mappings":"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"}
package/dist/wayfinder.js CHANGED
@@ -76,16 +76,29 @@ export const resolveWayfinderUrl = ({ originalUrl, selectedGateway, logger, }) =
76
76
  return new URL(originalUrl);
77
77
  };
78
78
  export class WayfinderEmitter extends EventEmitter {
79
- constructor({ onVerificationSucceeded, onVerificationFailed, onVerificationProgress, } = {}) {
79
+ constructor({ verification, routing } = {}) {
80
80
  super();
81
- if (onVerificationSucceeded) {
82
- this.on('verification-succeeded', onVerificationSucceeded);
83
- }
84
- if (onVerificationFailed) {
85
- this.on('verification-failed', onVerificationFailed);
81
+ if (verification) {
82
+ if (verification.onVerificationSucceeded) {
83
+ this.on('verification-succeeded', verification.onVerificationSucceeded);
84
+ }
85
+ if (verification.onVerificationFailed) {
86
+ this.on('verification-failed', verification.onVerificationFailed);
87
+ }
88
+ if (verification.onVerificationProgress) {
89
+ this.on('verification-progress', verification.onVerificationProgress);
90
+ }
86
91
  }
87
- if (onVerificationProgress) {
88
- this.on('verification-progress', onVerificationProgress);
92
+ if (routing) {
93
+ if (routing.onRoutingStarted) {
94
+ this.on('routing-started', routing.onRoutingStarted);
95
+ }
96
+ if (routing.onRoutingSkipped) {
97
+ this.on('routing-skipped', routing.onRoutingSkipped);
98
+ }
99
+ if (routing.onRoutingSucceeded) {
100
+ this.on('routing-succeeded', routing.onRoutingSucceeded);
101
+ }
89
102
  }
90
103
  }
91
104
  }
@@ -185,10 +198,14 @@ export function sandboxFromId(id) {
185
198
  * @param resolveUrl - the function to construct the redirect url for ar:// requests
186
199
  * @returns a wrapped fetch function that supports ar:// protocol and always returns Response
187
200
  */
188
- export const createWayfinderClient = ({ getGateways, resolveUrl, verifyData, selectGateway, emitter = new WayfinderEmitter(), logger = defaultLogger, strict = false, }) => {
201
+ export const wayfinderRequest = ({ getGateways, resolveUrl, verifyData, selectGateway, emitter = new WayfinderEmitter(), logger = defaultLogger, strict = false, }) => {
189
202
  return async (input, init) => {
190
- if (typeof input !== 'string' && !(input instanceof URL)) {
191
- logger?.debug('URL is not a string, skipping routing', {
203
+ const url = input instanceof URL ? input.toString() : input.toString();
204
+ console.log('URL', {
205
+ url,
206
+ });
207
+ if (!url.toString().startsWith('ar://')) {
208
+ logger?.debug('URL is not a wayfinder url, skipping routing', {
192
209
  input,
193
210
  });
194
211
  emitter?.emit('routing-skipped', {
@@ -196,9 +213,8 @@ export const createWayfinderClient = ({ getGateways, resolveUrl, verifyData, sel
196
213
  });
197
214
  return fetch(input, init);
198
215
  }
199
- const url = input.toString();
200
216
  emitter?.emit('routing-started', {
201
- originalUrl: url,
217
+ originalUrl: input.toString(),
202
218
  });
203
219
  const maxRetries = 3;
204
220
  const retryDelay = 1000;
@@ -207,8 +223,8 @@ export const createWayfinderClient = ({ getGateways, resolveUrl, verifyData, sel
207
223
  // select the target gateway
208
224
  const selectedGateway = await selectGateway({
209
225
  gateways: await getGateways(),
210
- path: input instanceof URL ? input.pathname.split('/')[1] : '',
211
- subdomain: input instanceof URL ? input.hostname.split('.')[0] : '',
226
+ path: url.split('/').slice(1).join('/'), // everything after the first /
227
+ subdomain: '',
212
228
  });
213
229
  logger?.debug('Selected gateway', {
214
230
  originalUrl: url,
@@ -216,7 +232,7 @@ export const createWayfinderClient = ({ getGateways, resolveUrl, verifyData, sel
216
232
  });
217
233
  // route the request to the target gateway
218
234
  const redirectUrl = resolveUrl({
219
- originalUrl: url,
235
+ originalUrl: url.toString(),
220
236
  selectedGateway,
221
237
  logger,
222
238
  });
@@ -332,15 +348,12 @@ export class Wayfinder {
332
348
  gatewaysProvider;
333
349
  /**
334
350
  * The routing strategy to use when routing requests.
335
- *
336
- * @example
337
- * const wayfinder = new Wayfinder({
338
- * strategy: new FastestPingStrategy({
339
- * timeoutMs: 1000,
340
- * }),
341
- * });
342
351
  */
343
352
  routingStrategy;
353
+ /**
354
+ * The verification strategy to use when verifying data.
355
+ */
356
+ verificationStrategy;
344
357
  /**
345
358
  * A helper function that resolves the redirect url for ar:// requests to a target gateway.
346
359
  *
@@ -399,18 +412,12 @@ export class Wayfinder {
399
412
  * });
400
413
  */
401
414
  verifyData;
402
- /**
403
- * Whether verification should be strict (blocking) or not.
404
- * If true, verification failures will cause requests to fail.
405
- * If false, verification will be performed asynchronously and failures will only emit events.
406
- */
407
- strict;
408
415
  /**
409
416
  * The logger used by this Wayfinder instance
410
417
  */
411
418
  logger;
412
419
  /**
413
- * The event emitter for wayfinder that emits verification events.
420
+ * The event emitter for wayfinder that emits routing and verification events.
414
421
  *
415
422
  * const wayfinder = new Wayfinder()
416
423
  *
@@ -425,17 +432,40 @@ export class Wayfinder {
425
432
  * or implement the events interface and pass it in, using callback functions
426
433
  *
427
434
  * const wayfinder = new Wayfinder({
428
- * events: {
429
- * onVerificationPassed: (event) => {
430
- * console.log('Verification passed!', event);
431
- * },
432
- * onVerificationFailed: (event) => {
435
+ * verificationSettings: {
436
+ * strategy: new HashVerificationStrategy({
437
+ * trustedGateways: [new URL('https://permagate.io')],
438
+ * }),
439
+ * events: {
440
+ * onVerificationProgress: (event) => {
441
+ * console.log('Verification progress!', event);
442
+ * },
443
+ * onVerificationSucceeded: (event) => {
444
+ * console.log('Verification passed!', event);
445
+ * },
446
+ * onVerificationFailed: (event) => {
433
447
  * console.log('Verification failed!', event);
434
448
  * },
435
449
  * onVerificationProgress: (event) => {
436
450
  * console.log('Verification progress!', event);
437
451
  * },
438
452
  * }
453
+ * routingSettings: {
454
+ * strategy: new FastestPingRoutingStrategy({
455
+ * timeoutMs: 1000,
456
+ * }),
457
+ * events: {
458
+ * onRoutingStarted: (event) => {
459
+ * console.log('Routing started!', event);
460
+ * },
461
+ * onRoutingSkipped: (event) => {
462
+ * console.log('Routing skipped!', event);
463
+ * },
464
+ * onRoutingSucceeded: (event) => {
465
+ * console.log('Routing succeeded!', event);
466
+ * },
467
+ * },
468
+ * }
439
469
  * })
440
470
  *
441
471
  * const response = await wayfinder.request('ar://example');
@@ -445,29 +475,58 @@ export class Wayfinder {
445
475
  * The constructor for the wayfinder
446
476
  * @param options - Wayfinder configuration options
447
477
  */
448
- constructor({ logger = defaultLogger, gatewaysProvider, routingStrategy = new FastestPingRoutingStrategy({
449
- timeoutMs: 1000,
450
- logger,
451
- }), verificationStrategy = new HashVerificationStrategy({
452
- trustedGateways: [new URL('https://permagate.io')],
453
- }), events = {
454
- onVerificationSucceeded: (event) => {
455
- logger.debug('Verification passed!', event);
456
- },
457
- onVerificationFailed: (event) => {
458
- logger.error('Verification failed!', event);
478
+ constructor({ logger = defaultLogger, gatewaysProvider, verificationSettings = {
479
+ enabled: true,
480
+ strict: false,
481
+ strategy: new HashVerificationStrategy({
482
+ trustedGateways: [new URL('https://permagate.io')],
483
+ }),
484
+ events: {
485
+ onVerificationProgress: (event) => {
486
+ logger.debug('Verification progress!', event);
487
+ },
488
+ onVerificationSucceeded: (event) => {
489
+ logger.debug('Verification succeeded!', event);
490
+ },
491
+ onVerificationFailed: (event) => {
492
+ logger.error('Verification failed!', event);
493
+ },
459
494
  },
460
- onVerificationProgress: (event) => {
461
- logger.debug('Verification progress!', event);
495
+ }, routingSettings = {
496
+ strategy: new FastestPingRoutingStrategy({
497
+ timeoutMs: 1000,
498
+ logger,
499
+ }),
500
+ events: {
501
+ onRoutingStarted: (event) => {
502
+ logger.debug('Routing started!', event);
503
+ },
504
+ onRoutingSkipped: (event) => {
505
+ logger.debug('Routing skipped!', event);
506
+ },
507
+ onRoutingSucceeded: (event) => {
508
+ logger.debug('Routing succeeded!', event);
509
+ },
462
510
  },
463
- }, strict = false, }) {
511
+ }, }) {
464
512
  this.logger = logger;
465
- this.routingStrategy = routingStrategy;
513
+ this.routingStrategy =
514
+ routingSettings.strategy ??
515
+ new FastestPingRoutingStrategy({
516
+ timeoutMs: 1000,
517
+ logger,
518
+ });
519
+ this.verificationStrategy =
520
+ verificationSettings.strategy ??
521
+ new HashVerificationStrategy({
522
+ trustedGateways: [new URL('https://permagate.io')],
523
+ });
466
524
  this.gatewaysProvider = gatewaysProvider;
467
- this.emitter = new WayfinderEmitter(events);
468
- this.verifyData =
469
- verificationStrategy.verifyData.bind(verificationStrategy);
470
- this.strict = strict;
525
+ this.emitter = new WayfinderEmitter({
526
+ verification: verificationSettings.events,
527
+ routing: routingSettings.events,
528
+ });
529
+ this.verifyData = this.verificationStrategy.verifyData.bind(this.verificationStrategy);
471
530
  // top level function to easily resolve wayfinder urls using the routing strategy and gateways provider
472
531
  this.resolveUrl = async ({ originalUrl, logger = this.logger }) => {
473
532
  const selectedGateway = await this.routingStrategy.selectGateway({
@@ -479,16 +538,16 @@ export class Wayfinder {
479
538
  logger,
480
539
  });
481
540
  };
482
- // create a wayfinder client with the routing strategy and gateways provider
483
- this.request = createWayfinderClient({
541
+ // create a wayfinder request function with the routing strategy and gateways provider
542
+ this.request = wayfinderRequest({
484
543
  getGateways: this.gatewaysProvider.getGateways.bind(this.gatewaysProvider),
544
+ verifyData: this.verifyData,
485
545
  selectGateway: this.routingStrategy.selectGateway.bind(this.routingStrategy),
486
546
  resolveUrl: resolveWayfinderUrl,
487
- verifyData: this.verifyData,
488
547
  emitter: this.emitter,
489
548
  logger: this.logger,
490
- strict,
549
+ strict: verificationSettings.strict,
491
550
  });
492
- logger.debug(`Wayfinder initialized with ${routingStrategy.constructor.name} routing strategy`);
551
+ logger.debug(`Wayfinder initialized with ${this.routingStrategy.constructor.name} routing strategy`);
493
552
  }
494
553
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ar.io/wayfinder-core",
3
- "version": "0.0.3-alpha.6",
3
+ "version": "0.0.4-alpha.0",
4
4
  "description": "WayFinder core library for intelligently routing to optimal AR.IO gateways",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -41,7 +41,7 @@
41
41
  "build": "npm run clean && tsc",
42
42
  "clean": "rimraf dist",
43
43
  "test": "npm run test:unit",
44
- "test:unit": "c8 node --import=../../register.mjs --test --enable-source-maps --trace-warnings 'src/**/*.test.ts'",
44
+ "test:unit": "c8 tsx --enable-source-maps --trace-uncaught --trace-warnings --trace-deprecation src/**/*.test.ts",
45
45
  "lint:fix": "biome check --write --unsafe",
46
46
  "lint:check": "biome check --unsafe",
47
47
  "format:fix": "biome format --write",
@@ -59,6 +59,7 @@
59
59
  },
60
60
  "devDependencies": {
61
61
  "@ar.io/sdk": "^3.13.0",
62
- "@types/node": "^24.0.0"
62
+ "@types/node": "^24.0.0",
63
+ "tsx": "^4.20.3"
63
64
  }
64
65
  }