@ar.io/wayfinder-core 1.7.0 → 1.7.1-alpha.1
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 +190 -652
- package/dist/client.d.ts +11 -98
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +54 -116
- package/dist/fetch.d.ts +23 -0
- package/dist/fetch.d.ts.map +1 -0
- package/dist/fetch.js +24 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/types.d.ts +20 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/wayfinder.d.ts +11 -12
- package/dist/wayfinder.d.ts.map +1 -1
- package/dist/wayfinder.js +21 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,10 +19,13 @@ yarn add @ar.io/wayfinder-core
|
|
|
19
19
|
```javascript
|
|
20
20
|
import { createWayfinderClient } from '@ar.io/wayfinder-core';
|
|
21
21
|
|
|
22
|
-
//
|
|
22
|
+
// Creates a Wayfinder client with sensible defaults:
|
|
23
|
+
// - Trusted peers gateway provider with caching (5 minute TTL)
|
|
24
|
+
// - Random routing strategy
|
|
25
|
+
// - Verification disabled
|
|
23
26
|
const wayfinder = createWayfinderClient();
|
|
24
27
|
|
|
25
|
-
// Use Wayfinder to fetch
|
|
28
|
+
// Use Wayfinder to fetch data using ar:// protocol
|
|
26
29
|
const response = await wayfinder.request('ar://example-name');
|
|
27
30
|
```
|
|
28
31
|
|
|
@@ -44,122 +47,65 @@ const gatewaysProvider = new NetworkGatewaysProvider({
|
|
|
44
47
|
});
|
|
45
48
|
|
|
46
49
|
const wayfinder = createWayfinderClient({
|
|
47
|
-
|
|
50
|
+
routingSettings: {
|
|
51
|
+
strategy: new FastestPingRoutingStrategy({ gatewaysProvider }),
|
|
52
|
+
},
|
|
48
53
|
});
|
|
49
54
|
```
|
|
50
55
|
|
|
51
|
-
###
|
|
56
|
+
### Enable Verification
|
|
52
57
|
|
|
53
58
|
```javascript
|
|
54
59
|
import {
|
|
55
60
|
createWayfinderClient,
|
|
56
|
-
FastestPingRoutingStrategy,
|
|
57
61
|
HashVerificationStrategy,
|
|
58
62
|
} from '@ar.io/wayfinder-core';
|
|
59
63
|
|
|
60
|
-
const trustedGateways = [new URL('https://permagate.io')];
|
|
61
|
-
|
|
62
64
|
const wayfinder = createWayfinderClient({
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
verificationSettings: {
|
|
66
|
+
enabled: true,
|
|
67
|
+
strategy: new HashVerificationStrategy({
|
|
68
|
+
trustedGateways: [new URL('https://permagate.io')],
|
|
69
|
+
}),
|
|
70
|
+
strict: true, // Fail requests on verification errors
|
|
71
|
+
},
|
|
67
72
|
});
|
|
68
73
|
```
|
|
69
74
|
|
|
70
|
-
|
|
71
|
-
> The legacy `trustedGateways` option on `createWayfinderClient` is deprecated.
|
|
72
|
-
> Configure trusted gateways on the verification strategy instead, as shown
|
|
73
|
-
> above.
|
|
74
|
-
|
|
75
|
-
### Configuration Options
|
|
76
|
-
|
|
77
|
-
> [!IMPORTANT]
|
|
78
|
-
> `createWayfinderClient` only honors the `cache`, `routingStrategy`,
|
|
79
|
-
> `verificationStrategy`, and `telemetry` options. All other legacy options are
|
|
80
|
-
> deprecated and ignored. Supply concrete strategy instances or instantiate
|
|
81
|
-
> `Wayfinder` directly for advanced customization.
|
|
82
|
-
|
|
83
|
-
By default the helper constructs a
|
|
84
|
-
`TrustedPeersGatewaysProvider('https://permagate.io')`, applies a
|
|
85
|
-
`RandomRoutingStrategy`, and disables verification.
|
|
86
|
-
|
|
87
|
-
```javascript
|
|
88
|
-
import {
|
|
89
|
-
createWayfinderClient,
|
|
90
|
-
FastestPingRoutingStrategy,
|
|
91
|
-
HashVerificationStrategy,
|
|
92
|
-
} from '@ar.io/wayfinder-core';
|
|
75
|
+
Wayfinder Core provides helper functions to construct routing and verification strategies:
|
|
93
76
|
|
|
94
|
-
|
|
95
|
-
cache: { ttlSeconds: 600 },
|
|
96
|
-
routingStrategy: new FastestPingRoutingStrategy(),
|
|
97
|
-
verificationStrategy: new HashVerificationStrategy({
|
|
98
|
-
trustedGateways: [new URL('https://permagate.io')],
|
|
99
|
-
}),
|
|
100
|
-
});
|
|
101
|
-
```
|
|
77
|
+
### createRoutingStrategy
|
|
102
78
|
|
|
103
|
-
|
|
104
|
-
directly:
|
|
79
|
+
Create routing strategies with a simple string identifier:
|
|
105
80
|
|
|
106
81
|
```javascript
|
|
107
|
-
import {
|
|
108
|
-
FastestPingRoutingStrategy,
|
|
109
|
-
HashVerificationStrategy,
|
|
110
|
-
NetworkGatewaysProvider,
|
|
111
|
-
Wayfinder,
|
|
112
|
-
} from '@ar.io/wayfinder-core';
|
|
113
|
-
import { ARIO } from '@ar.io/sdk';
|
|
82
|
+
import { createRoutingStrategy } from '@ar.io/wayfinder-core';
|
|
114
83
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
84
|
+
// Create a random routing strategy
|
|
85
|
+
const randomStrategy = createRoutingStrategy({
|
|
86
|
+
strategy: 'random',
|
|
87
|
+
gatewaysProvider: myGatewaysProvider,
|
|
88
|
+
logger: myLogger,
|
|
120
89
|
});
|
|
121
90
|
|
|
122
|
-
|
|
123
|
-
new URL('https://arweave.net'),
|
|
124
|
-
new URL('https://permagate.io'),
|
|
125
|
-
];
|
|
126
|
-
|
|
127
|
-
const wayfinder = new Wayfinder({
|
|
128
|
-
gatewaysProvider,
|
|
129
|
-
routingSettings: {
|
|
130
|
-
strategy: new FastestPingRoutingStrategy({ gatewaysProvider }),
|
|
131
|
-
},
|
|
132
|
-
verificationSettings: {
|
|
133
|
-
strategy: new HashVerificationStrategy({
|
|
134
|
-
trustedGateways,
|
|
135
|
-
}),
|
|
136
|
-
},
|
|
137
|
-
telemetrySettings: { enabled: true },
|
|
138
|
-
});
|
|
91
|
+
// Available strategies: 'random', 'fastest', 'balanced', 'preferred'
|
|
139
92
|
```
|
|
140
93
|
|
|
141
|
-
###
|
|
94
|
+
### createVerificationStrategy
|
|
142
95
|
|
|
143
|
-
|
|
96
|
+
Create verification strategies with a simple string identifier:
|
|
144
97
|
|
|
145
98
|
```javascript
|
|
146
|
-
import {
|
|
147
|
-
createWayfinderClient,
|
|
148
|
-
NetworkGatewaysProvider,
|
|
149
|
-
RandomRoutingStrategy,
|
|
150
|
-
} from '@ar.io/wayfinder-core';
|
|
151
|
-
import { ARIO } from '@ar.io/sdk';
|
|
99
|
+
import { createVerificationStrategy } from '@ar.io/wayfinder-core';
|
|
152
100
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
101
|
+
// Create a hash verification strategy
|
|
102
|
+
const hashStrategy = createVerificationStrategy({
|
|
103
|
+
strategy: 'hash',
|
|
104
|
+
trustedGateways: [new URL('https://permagate.io')],
|
|
105
|
+
logger: myLogger,
|
|
158
106
|
});
|
|
159
107
|
|
|
160
|
-
|
|
161
|
-
routingStrategy: new RandomRoutingStrategy({ gatewaysProvider }),
|
|
162
|
-
});
|
|
108
|
+
// Available strategies: 'hash', 'data-root', 'remote', 'disabled'
|
|
163
109
|
```
|
|
164
110
|
|
|
165
111
|
## ar:// Protocol
|
|
@@ -167,14 +113,14 @@ const wayfinder = createWayfinderClient({
|
|
|
167
113
|
Wayfinder supports several ar:// URL formats:
|
|
168
114
|
|
|
169
115
|
```bash
|
|
170
|
-
ar://TRANSACTION_ID
|
|
171
|
-
ar://NAME
|
|
172
|
-
ar:///info
|
|
116
|
+
ar://TRANSACTION_ID # Direct transaction ID
|
|
117
|
+
ar://NAME # ArNS name (paths supported)
|
|
118
|
+
ar:///info # Gateway endpoint (/info)
|
|
173
119
|
```
|
|
174
120
|
|
|
175
121
|
## Dynamic Routing
|
|
176
122
|
|
|
177
|
-
Wayfinder supports a `resolveUrl` method which generates dynamic redirect URLs to a target gateway based on the provided routing strategy.
|
|
123
|
+
Wayfinder supports a `resolveUrl` method which generates dynamic redirect URLs to a target gateway based on the provided routing strategy. This function can be used to directly replace any hard-coded gateway URLs, and instead use Wayfinder's routing logic to select a gateway for the request.
|
|
178
124
|
|
|
179
125
|
#### ArNS names
|
|
180
126
|
|
|
@@ -198,7 +144,7 @@ const redirectUrl = await wayfinder.resolveUrl({
|
|
|
198
144
|
// results in https://<selected-gateway>/example-tx-id
|
|
199
145
|
```
|
|
200
146
|
|
|
201
|
-
#### Legacy
|
|
147
|
+
#### Legacy URLs
|
|
202
148
|
|
|
203
149
|
Given a legacy arweave.net or arweave.dev URL, the redirect URL will be the same as the original URL, but with the gateway selected by Wayfinder's routing strategy.
|
|
204
150
|
|
|
@@ -222,35 +168,34 @@ const redirectUrl = await wayfinder.resolveUrl({
|
|
|
222
168
|
|
|
223
169
|
## Gateway Providers
|
|
224
170
|
|
|
225
|
-
Gateway providers
|
|
171
|
+
Gateway providers supply the list of gateways for routing. **By default, `createWayfinderClient` uses a cached `TrustedPeersGatewaysProvider`**.
|
|
226
172
|
|
|
227
173
|
| Provider | Description | Use Case |
|
|
228
174
|
| ------------------------------ | ---------------------------------------------- | --------------------------------------- |
|
|
229
|
-
| `NetworkGatewaysProvider` | Returns gateways from AR.IO Network
|
|
230
|
-
| `TrustedPeersGatewaysProvider` | Fetches
|
|
231
|
-
| `StaticGatewaysProvider` | Returns a static list of gateways
|
|
232
|
-
| `SimpleCacheGatewaysProvider` |
|
|
233
|
-
| `LocalStorageGatewaysProvider` |
|
|
175
|
+
| `NetworkGatewaysProvider` | Returns gateways from AR.IO Network | Leverage AR.IO Network with quality filtering |
|
|
176
|
+
| `TrustedPeersGatewaysProvider` | Fetches from trusted gateway's peers | Dynamic gateway discovery (default) |
|
|
177
|
+
| `StaticGatewaysProvider` | Returns a static list of gateways | Testing or specific gateways |
|
|
178
|
+
| `SimpleCacheGatewaysProvider` | In-memory caching wrapper | Reduce API calls (used by default) |
|
|
179
|
+
| `LocalStorageGatewaysProvider` | Browser localStorage caching | Persistent caching (used by default in browsers) |
|
|
234
180
|
|
|
235
|
-
|
|
181
|
+
#### NetworkGatewaysProvider
|
|
236
182
|
|
|
237
|
-
Returns a list of gateways from the ARIO Network based on on-chain
|
|
183
|
+
Returns a list of gateways from the ARIO Network based on on-chain [Gateway Address Registry](https://docs.ar.io/learn/gateways/gateway-registry). You can specify on-chain metrics for gateways to prioritize the highest quality gateways. This requires installing the `@ar.io/sdk` package and importing the `ARIO` object.
|
|
238
184
|
|
|
239
185
|
```javascript
|
|
240
|
-
|
|
186
|
+
import { NetworkGatewaysProvider } from '@ar.io/wayfinder-core';
|
|
187
|
+
import { ARIO } from '@ar.io/sdk';
|
|
188
|
+
|
|
241
189
|
const gatewayProvider = new NetworkGatewaysProvider({
|
|
242
190
|
ario: ARIO.mainnet(),
|
|
243
|
-
sortBy: 'operatorStake',
|
|
244
|
-
sortOrder: 'desc',
|
|
245
|
-
limit: 10,
|
|
246
|
-
filter: (gateway) =>
|
|
247
|
-
// use only active gateways that did not fail in the last epoch
|
|
248
|
-
return gateway.status === 'joined' && gateway.stats.failedConsecutiveEpochs === 0;
|
|
249
|
-
},
|
|
191
|
+
sortBy: 'operatorStake',
|
|
192
|
+
sortOrder: 'desc',
|
|
193
|
+
limit: 10,
|
|
194
|
+
filter: (gateway) => gateway.status === 'joined',
|
|
250
195
|
});
|
|
251
196
|
```
|
|
252
197
|
|
|
253
|
-
|
|
198
|
+
#### TrustedPeersGatewaysProvider
|
|
254
199
|
|
|
255
200
|
Fetches a dynamic list of trusted peer gateways from an AR.IO gateway's `/ar-io/peers` endpoint. This provider is useful for discovering available gateways from a trusted source.
|
|
256
201
|
|
|
@@ -258,22 +203,7 @@ Fetches a dynamic list of trusted peer gateways from an AR.IO gateway's `/ar-io/
|
|
|
258
203
|
import { TrustedPeersGatewaysProvider } from '@ar.io/wayfinder-core';
|
|
259
204
|
|
|
260
205
|
const gatewayProvider = new TrustedPeersGatewaysProvider({
|
|
261
|
-
trustedGateway: 'https://arweave.net',
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
// The provider will fetch the peer list from https://arweave.net/ar-io/peers
|
|
265
|
-
// and return an array of gateway URLs from the response
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
### StaticGatewaysProvider
|
|
269
|
-
|
|
270
|
-
The static gateway provider returns a list of gateways that you provide. This is useful for testing or for users who want to use a specific gateway for all requests.
|
|
271
|
-
|
|
272
|
-
```javascript
|
|
273
|
-
import { StaticGatewaysProvider } from '@ar.io/wayfinder-core';
|
|
274
|
-
|
|
275
|
-
const gatewayProvider = new StaticGatewaysProvider({
|
|
276
|
-
gateways: ['https://arweave.net'],
|
|
206
|
+
trustedGateway: 'https://arweave.net',
|
|
277
207
|
});
|
|
278
208
|
```
|
|
279
209
|
|
|
@@ -290,109 +220,32 @@ Wayfinder supports multiple routing strategies to select target gateways for you
|
|
|
290
220
|
| `PreferredWithFallbackRoutingStrategy` | Uses a preferred gateway, with a fallback strategy if the preferred gateway is not available | Good for performance and resilience. Ideal for builders who run their own gateways. |
|
|
291
221
|
| `CompositeRoutingStrategy` | Chains multiple routing strategies together, trying each sequentially until one succeeds | Good for complex fallback scenarios and maximum resilience |
|
|
292
222
|
|
|
293
|
-
|
|
223
|
+
#### RandomRoutingStrategy
|
|
294
224
|
|
|
295
225
|
Selects a random gateway from a list of gateways.
|
|
296
226
|
|
|
297
227
|
```javascript
|
|
298
|
-
import { RandomRoutingStrategy
|
|
299
|
-
import { ARIO } from '@ar.io/sdk';
|
|
300
|
-
|
|
301
|
-
// Option 1: Use with static gateways (override gatewaysProvider if provided)
|
|
302
|
-
const routingStrategy = new RandomRoutingStrategy();
|
|
303
|
-
const gateway = await routingStrategy.selectGateway({
|
|
304
|
-
gateways: [new URL('https://arweave.net'), new URL('https://permagate.io')],
|
|
305
|
-
});
|
|
306
|
-
|
|
307
|
-
// Option 2: Use with gatewaysProvider (fetches dynamically)
|
|
308
|
-
const routingStrategy2 = new RandomRoutingStrategy({
|
|
309
|
-
gatewaysProvider: new NetworkGatewaysProvider({
|
|
310
|
-
ario: ARIO.mainnet(),
|
|
311
|
-
sortBy: 'operatorStake',
|
|
312
|
-
limit: 10,
|
|
313
|
-
}),
|
|
314
|
-
});
|
|
315
|
-
const gateway2 = await routingStrategy2.selectGateway(); // uses gatewaysProvider
|
|
316
|
-
|
|
317
|
-
// Option 3: Override gatewaysProvider with static gateways
|
|
318
|
-
const gateway3 = await routingStrategy2.selectGateway({
|
|
319
|
-
gateways: [new URL('https://custom-gateway.net')], // overrides gatewaysProvider
|
|
320
|
-
});
|
|
321
|
-
```
|
|
322
|
-
|
|
323
|
-
### StaticRoutingStrategy
|
|
324
|
-
|
|
325
|
-
```javascript
|
|
326
|
-
import { StaticRoutingStrategy } from '@ar.io/wayfinder-core';
|
|
327
|
-
|
|
328
|
-
const routingStrategy = new StaticRoutingStrategy({
|
|
329
|
-
gateway: 'https://arweave.net',
|
|
330
|
-
});
|
|
331
|
-
|
|
332
|
-
const gateway = await routingStrategy.selectGateway(); // always returns the same gateway
|
|
333
|
-
```
|
|
334
|
-
|
|
335
|
-
### RoundRobinRoutingStrategy
|
|
336
|
-
|
|
337
|
-
Selects gateways in round-robin order. The gateway list is stored in memory and is not persisted across instances. You must provide either `gateways` OR `gatewaysProvider` (not both).
|
|
338
|
-
|
|
339
|
-
```javascript
|
|
340
|
-
import { RoundRobinRoutingStrategy, NetworkGatewaysProvider } from '@ar.io/wayfinder-core';
|
|
341
|
-
import { ARIO } from '@ar.io/sdk';
|
|
228
|
+
import { RandomRoutingStrategy } from '@ar.io/wayfinder-core';
|
|
342
229
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
gateways: [new URL('https://arweave.net'), new URL('https://permagate.io')],
|
|
230
|
+
const strategy = new RandomRoutingStrategy({
|
|
231
|
+
gatewaysProvider: myGatewaysProvider,
|
|
346
232
|
});
|
|
347
|
-
|
|
348
|
-
// use with gatewaysProvider (loaded once and memoized)
|
|
349
|
-
const routingStrategy2 = new RoundRobinRoutingStrategy({
|
|
350
|
-
gatewaysProvider: new NetworkGatewaysProvider({
|
|
351
|
-
ario: ARIO.mainnet(),
|
|
352
|
-
sortBy: 'operatorStake',
|
|
353
|
-
sortOrder: 'desc',
|
|
354
|
-
limit: 10,
|
|
355
|
-
}),
|
|
356
|
-
});
|
|
357
|
-
|
|
358
|
-
const gateway = await routingStrategy.selectGateway(); // returns the next gateway in round-robin order
|
|
359
233
|
```
|
|
360
234
|
|
|
361
|
-
|
|
235
|
+
#### FastestPingRoutingStrategy
|
|
362
236
|
|
|
363
|
-
Selects the fastest gateway based on
|
|
237
|
+
Selects the fastest gateway based on ping time. This strategy pings all available gateways and selects the one with the lowest latency.
|
|
364
238
|
|
|
365
239
|
```javascript
|
|
366
|
-
import { FastestPingRoutingStrategy
|
|
367
|
-
import { ARIO } from '@ar.io/sdk';
|
|
368
|
-
|
|
369
|
-
// use with static gateways (override gatewaysProvider if provided)
|
|
370
|
-
const routingStrategy = new FastestPingRoutingStrategy({
|
|
371
|
-
timeoutMs: 1000,
|
|
372
|
-
});
|
|
373
|
-
const gateway = await routingStrategy.selectGateway({
|
|
374
|
-
gateways: [new URL('https://slow.net'), new URL('https://medium.net'), new URL('https://fast.net')],
|
|
375
|
-
});
|
|
240
|
+
import { FastestPingRoutingStrategy } from '@ar.io/wayfinder-core';
|
|
376
241
|
|
|
377
|
-
|
|
378
|
-
const routingStrategy2 = new FastestPingRoutingStrategy({
|
|
242
|
+
const strategy = new FastestPingRoutingStrategy({
|
|
379
243
|
timeoutMs: 1000,
|
|
380
|
-
gatewaysProvider:
|
|
381
|
-
ario: ARIO.mainnet(),
|
|
382
|
-
sortBy: 'operatorStake',
|
|
383
|
-
limit: 20,
|
|
384
|
-
}),
|
|
385
|
-
});
|
|
386
|
-
const gateway2 = await routingStrategy2.selectGateway({ path: '/ar-io/info' }); // uses gatewaysProvider
|
|
387
|
-
|
|
388
|
-
// override the gatewaysProvider with a static list of gateways
|
|
389
|
-
const gateway3 = await routingStrategy2.selectGateway({
|
|
390
|
-
gateways: [new URL('https://priority-gateway.net')], // overrides gatewaysProvider
|
|
391
|
-
path: '/ar-io/info'
|
|
244
|
+
gatewaysProvider: myGatewaysProvider,
|
|
392
245
|
});
|
|
393
246
|
```
|
|
394
247
|
|
|
395
|
-
|
|
248
|
+
#### PreferredWithFallbackRoutingStrategy
|
|
396
249
|
|
|
397
250
|
Uses a preferred gateway, with a fallback strategy if the preferred gateway is not available. This is useful for builders who run their own gateways and want to use their own gateway as the preferred gateway, but also want to have a fallback strategy in case their gateway is not available.
|
|
398
251
|
|
|
@@ -402,17 +255,28 @@ Uses a preferred gateway, with a fallback strategy if the preferred gateway is n
|
|
|
402
255
|
```javascript
|
|
403
256
|
import { PreferredWithFallbackRoutingStrategy, FastestPingRoutingStrategy } from '@ar.io/wayfinder-core';
|
|
404
257
|
|
|
405
|
-
const
|
|
406
|
-
preferredGateway: 'https://
|
|
407
|
-
fallbackStrategy: new FastestPingRoutingStrategy({
|
|
408
|
-
timeoutMs: 500,
|
|
409
|
-
}),
|
|
258
|
+
const strategy = new PreferredWithFallbackRoutingStrategy({
|
|
259
|
+
preferredGateway: 'https://my-gateway.com',
|
|
260
|
+
fallbackStrategy: new FastestPingRoutingStrategy({ timeoutMs: 500 }),
|
|
410
261
|
});
|
|
411
262
|
```
|
|
412
263
|
|
|
413
|
-
|
|
264
|
+
#### CompositeRoutingStrategy
|
|
265
|
+
|
|
266
|
+
The `CompositeRoutingStrategy` allows you to chain multiple routing strategies together, providing maximum resilience by trying each strategy in sequence until one succeeds. This is ideal for complex fallback scenarios where you want to combine different routing approaches.
|
|
267
|
+
|
|
268
|
+
**How it works:**
|
|
269
|
+
|
|
270
|
+
1. Tries each strategy in the order they're provided
|
|
271
|
+
2. If a strategy successfully returns a gateway, that gateway is used (remaining strategies are skipped)
|
|
272
|
+
3. If a strategy throws an error, moves to the next strategy
|
|
273
|
+
4. If all strategies fail, throws an error
|
|
274
|
+
|
|
275
|
+
**Common use cases:**
|
|
414
276
|
|
|
415
|
-
|
|
277
|
+
- **Performance + Resilience**: Try fastest ping first, fallback to random if ping fails
|
|
278
|
+
- **Preferred + Network**: Use your own gateway first, fallback to AR.IO network selection
|
|
279
|
+
- **Multi-tier Fallback**: Try premium gateways, then standard gateways, then any available gateway
|
|
416
280
|
|
|
417
281
|
```javascript
|
|
418
282
|
import {
|
|
@@ -424,9 +288,10 @@ import {
|
|
|
424
288
|
} from '@ar.io/wayfinder-core';
|
|
425
289
|
import { ARIO } from '@ar.io/sdk';
|
|
426
290
|
|
|
427
|
-
// Example 1:
|
|
428
|
-
const
|
|
291
|
+
// Example 1: Performance-first with resilience fallback
|
|
292
|
+
const performanceStrategy = new CompositeRoutingStrategy({
|
|
429
293
|
strategies: [
|
|
294
|
+
// Try fastest ping first (high performance, but may fail if all gateways are slow)
|
|
430
295
|
new FastestPingRoutingStrategy({
|
|
431
296
|
timeoutMs: 500,
|
|
432
297
|
gatewaysProvider: new NetworkGatewaysProvider({
|
|
@@ -435,224 +300,48 @@ const strategy = new CompositeRoutingStrategy({
|
|
|
435
300
|
limit: 10,
|
|
436
301
|
}),
|
|
437
302
|
}),
|
|
438
|
-
|
|
303
|
+
// Fallback to random selection (guaranteed to work if gateways exist)
|
|
304
|
+
new RandomRoutingStrategy({
|
|
305
|
+
gatewaysProvider: new NetworkGatewaysProvider({
|
|
306
|
+
ario: ARIO.mainnet(),
|
|
307
|
+
sortBy: 'operatorStake',
|
|
308
|
+
limit: 20, // Use more gateways for fallback
|
|
309
|
+
}),
|
|
310
|
+
}),
|
|
439
311
|
],
|
|
440
312
|
});
|
|
441
313
|
|
|
442
|
-
// Example 2:
|
|
443
|
-
const
|
|
314
|
+
// Example 2: Preferred gateway with multi-tier fallback
|
|
315
|
+
const preferredStrategy = new CompositeRoutingStrategy({
|
|
444
316
|
strategies: [
|
|
445
|
-
|
|
446
|
-
new
|
|
447
|
-
|
|
448
|
-
],
|
|
449
|
-
});
|
|
450
|
-
|
|
451
|
-
const gateway = await strategy.selectGateway({
|
|
452
|
-
gateways: [new URL('https://gateway1.com'), new URL('https://gateway2.com')],
|
|
453
|
-
});
|
|
454
|
-
```
|
|
455
|
-
|
|
456
|
-
**How it works:**
|
|
457
|
-
1. The composite strategy tries each routing strategy in order
|
|
458
|
-
2. If a strategy successfully returns a gateway, that gateway is used
|
|
459
|
-
3. If a strategy throws an error, the next strategy is tried
|
|
460
|
-
4. If all strategies fail, an error is thrown
|
|
461
|
-
5. The first successful strategy short-circuits the process (remaining strategies are not tried)
|
|
462
|
-
|
|
463
|
-
**Common Use Cases:**
|
|
464
|
-
- **Performance + Resilience**: Try fastest ping first, fallback to random if ping fails
|
|
465
|
-
- **Preferred + Network**: Use your own gateway first, fallback to AR.IO network selection
|
|
466
|
-
- **Multi-tier Fallback**: Try premium gateways, then standard gateways, then any available gateway
|
|
467
|
-
- **Development + Production**: Use local gateway in development, fallback to production gateways
|
|
468
|
-
|
|
469
|
-
### Strategy Composition Examples
|
|
470
|
-
|
|
471
|
-
Here are a few “lego-style” examples showing how existing routing strategies can
|
|
472
|
-
be composed to suit different use cases. Each strategy implements
|
|
473
|
-
`RoutingStrategy`, so they can be wrapped and combined freely.
|
|
474
|
-
|
|
475
|
-
#### Random + Ping health checks
|
|
476
|
-
|
|
477
|
-
Pick a random gateway, then verify it responds with a `HEAD` request before
|
|
478
|
-
returning it.
|
|
479
|
-
|
|
480
|
-
```ts
|
|
481
|
-
import {
|
|
482
|
-
RandomRoutingStrategy,
|
|
483
|
-
PingRoutingStrategy,
|
|
484
|
-
} from "@ar.io/wayfinder-core";
|
|
485
|
-
|
|
486
|
-
const strategy = new PingRoutingStrategy({
|
|
487
|
-
routingStrategy: new RandomRoutingStrategy(),
|
|
488
|
-
retries: 2,
|
|
489
|
-
timeoutMs: 500,
|
|
490
|
-
});
|
|
491
|
-
```
|
|
492
|
-
|
|
493
|
-
#### Fastest ping wrapped with a simple cache
|
|
494
|
-
|
|
495
|
-
Find the lowest-latency gateway and cache the result for five minutes to avoid
|
|
496
|
-
constant pings.
|
|
497
|
-
|
|
498
|
-
```ts
|
|
499
|
-
import {
|
|
500
|
-
FastestPingRoutingStrategy,
|
|
501
|
-
SimpleCacheRoutingStrategy,
|
|
502
|
-
} from "@ar.io/wayfinder-core";
|
|
503
|
-
|
|
504
|
-
const strategy = new SimpleCacheRoutingStrategy({
|
|
505
|
-
routingStrategy: new FastestPingRoutingStrategy({ timeoutMs: 500 }),
|
|
506
|
-
ttlSeconds: 300,
|
|
507
|
-
});
|
|
508
|
-
```
|
|
509
|
-
|
|
510
|
-
#### Preferred gateway + network fallback strategy
|
|
511
|
-
|
|
512
|
-
Attempt to use a favorite gateway, but fallback to a fastest pinging strategy using the ARIO Network if it fails.
|
|
513
|
-
|
|
514
|
-
```ts
|
|
515
|
-
import {
|
|
516
|
-
PreferredWithFallbackRoutingStrategy,
|
|
517
|
-
RandomRoutingStrategy,
|
|
518
|
-
PingRoutingStrategy,
|
|
519
|
-
NetworkGatewaysProvider,
|
|
520
|
-
} from "@ar.io/wayfinder-core";
|
|
521
|
-
import { ARIO } from '@ar.io/sdk';
|
|
522
|
-
|
|
523
|
-
// these will be our fallback gateways
|
|
524
|
-
const gatewayProvider = new NetworkGatewaysProvider({
|
|
525
|
-
ario: ARIO.mainnet(),
|
|
526
|
-
sortBy: 'operatorStake',
|
|
527
|
-
limit: 5,
|
|
528
|
-
});
|
|
529
|
-
|
|
530
|
-
// this is our fallback strategy if our preferred gateway fails
|
|
531
|
-
const fastestPingStrategy = new FastestPingRoutingStrategy({
|
|
532
|
-
timeoutMs: 500,
|
|
533
|
-
gatewaysProvider: gatewayProvider,
|
|
534
|
-
});
|
|
535
|
-
|
|
536
|
-
// compose the strategies together, the preferred gateway will be used first, and if it fails, the fallback strategy will be used.
|
|
537
|
-
const strategy = new PreferredWithFallbackRoutingStrategy({
|
|
538
|
-
preferredGateway: "https://my-gateway.example",
|
|
539
|
-
fallbackStrategy: fastestPingStrategy,
|
|
540
|
-
});
|
|
541
|
-
```
|
|
542
|
-
|
|
543
|
-
#### Round-robin + ping verification
|
|
544
|
-
|
|
545
|
-
Cycle through gateways sequentially, checking each one’s health before use.
|
|
546
|
-
|
|
547
|
-
```ts
|
|
548
|
-
import {
|
|
549
|
-
RoundRobinRoutingStrategy,
|
|
550
|
-
PingRoutingStrategy,
|
|
551
|
-
NetworkGatewaysProvider,
|
|
552
|
-
} from "@ar.io/wayfinder-core";
|
|
553
|
-
import { ARIO } from '@ar.io/sdk';
|
|
554
|
-
|
|
555
|
-
// use static gateways
|
|
556
|
-
const strategy = new PingRoutingStrategy({
|
|
557
|
-
routingStrategy: new RoundRobinRoutingStrategy({
|
|
558
|
-
gateways: [new URL("https://gw1"), new URL("https://gw2")],
|
|
559
|
-
}),
|
|
560
|
-
});
|
|
561
|
-
|
|
562
|
-
// use a dynamic list of gateways from the ARIO Network
|
|
563
|
-
const strategy2 = new PingRoutingStrategy({
|
|
564
|
-
routingStrategy: new RoundRobinRoutingStrategy({
|
|
565
|
-
gatewaysProvider: new NetworkGatewaysProvider({
|
|
566
|
-
ario: ARIO.mainnet(),
|
|
567
|
-
sortBy: 'operatorStake',
|
|
568
|
-
limit: 5,
|
|
317
|
+
// First, try your preferred gateway
|
|
318
|
+
new StaticRoutingStrategy({
|
|
319
|
+
gateway: 'https://my-preferred-gateway.com'
|
|
569
320
|
}),
|
|
570
|
-
|
|
571
|
-
});
|
|
572
|
-
```
|
|
573
|
-
|
|
574
|
-
#### Cache around any composed strategy
|
|
575
|
-
|
|
576
|
-
Because `SimpleCacheRoutingStrategy` accepts any `RoutingStrategy`, you can
|
|
577
|
-
cache more complex compositions too.
|
|
578
|
-
|
|
579
|
-
```ts
|
|
580
|
-
import {
|
|
581
|
-
RandomRoutingStrategy,
|
|
582
|
-
PingRoutingStrategy,
|
|
583
|
-
SimpleCacheRoutingStrategy,
|
|
584
|
-
NetworkGatewaysProvider,
|
|
585
|
-
} from "@ar.io/wayfinder-core";
|
|
586
|
-
import { ARIO } from '@ar.io/sdk';
|
|
587
|
-
|
|
588
|
-
// use a dynamic list of gateways from the ARIO Network
|
|
589
|
-
const randomStrategy = new RandomRoutingStrategy({
|
|
590
|
-
gatewaysProvider: new NetworkGatewaysProvider({
|
|
591
|
-
ario: ARIO.mainnet(),
|
|
592
|
-
sortBy: 'operatorStake',
|
|
593
|
-
limit: 20,
|
|
594
|
-
}),
|
|
595
|
-
});
|
|
596
|
-
|
|
597
|
-
// wrap the random strategy with a ping strategy
|
|
598
|
-
const pingRandom = new PingRoutingStrategy({
|
|
599
|
-
routingStrategy: randomStrategy,
|
|
600
|
-
});
|
|
601
|
-
|
|
602
|
-
// wrap the ping random strategy with a cache strategy, caching the selected gateway for 10 minutes
|
|
603
|
-
const cachedStrategy = new SimpleCacheRoutingStrategy({
|
|
604
|
-
routingStrategy: pingRandom,
|
|
605
|
-
ttlSeconds: 600,
|
|
606
|
-
});
|
|
607
|
-
```
|
|
608
|
-
|
|
609
|
-
#### Complex multi-strategy fallback with CompositeRoutingStrategy
|
|
610
|
-
|
|
611
|
-
Chain multiple strategies together for maximum resilience - try fastest ping first, then fall back to random selection if ping fails.
|
|
612
|
-
|
|
613
|
-
```ts
|
|
614
|
-
import {
|
|
615
|
-
CompositeRoutingStrategy,
|
|
616
|
-
FastestPingRoutingStrategy,
|
|
617
|
-
RandomRoutingStrategy,
|
|
618
|
-
NetworkGatewaysProvider,
|
|
619
|
-
} from "@ar.io/wayfinder-core";
|
|
620
|
-
import { ARIO } from '@ar.io/sdk';
|
|
621
|
-
|
|
622
|
-
// Define gateway provider for both strategies
|
|
623
|
-
const gatewayProvider = new NetworkGatewaysProvider({
|
|
624
|
-
ario: ARIO.mainnet(),
|
|
625
|
-
sortBy: 'operatorStake',
|
|
626
|
-
limit: 15,
|
|
627
|
-
});
|
|
628
|
-
|
|
629
|
-
// Create a composite strategy that tries fastest ping first, then random
|
|
630
|
-
const strategy = new CompositeRoutingStrategy({
|
|
631
|
-
strategies: [
|
|
632
|
-
// Try fastest ping first (high performance, but may fail if all gateways are slow)
|
|
321
|
+
// If that fails, try fastest ping from top-tier gateways
|
|
633
322
|
new FastestPingRoutingStrategy({
|
|
634
|
-
timeoutMs:
|
|
635
|
-
gatewaysProvider:
|
|
323
|
+
timeoutMs: 1000,
|
|
324
|
+
gatewaysProvider: new NetworkGatewaysProvider({
|
|
325
|
+
ario: ARIO.mainnet(),
|
|
326
|
+
sortBy: 'operatorStake',
|
|
327
|
+
limit: 5, // Only top 5 gateways
|
|
328
|
+
}),
|
|
636
329
|
}),
|
|
637
|
-
//
|
|
330
|
+
// Final fallback: any random gateway from a larger pool
|
|
638
331
|
new RandomRoutingStrategy({
|
|
639
|
-
gatewaysProvider:
|
|
332
|
+
gatewaysProvider: new NetworkGatewaysProvider({
|
|
333
|
+
ario: ARIO.mainnet(),
|
|
334
|
+
limit: 50, // Larger pool for maximum availability
|
|
335
|
+
}),
|
|
640
336
|
}),
|
|
641
337
|
],
|
|
642
338
|
});
|
|
643
|
-
```
|
|
644
|
-
|
|
645
|
-
In all cases, you can supply the composed strategy to `Wayfinder` (or whatever
|
|
646
|
-
router factory you use) and pass in a gateways provider:
|
|
647
339
|
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
gateways: [new URL("https://gw1"), new URL("https://gw2")],
|
|
654
|
-
}),
|
|
655
|
-
routingStrategy: strategy, // any of the compositions above
|
|
340
|
+
// Use with createWayfinderClient
|
|
341
|
+
const wayfinder = createWayfinderClient({
|
|
342
|
+
routingSettings: {
|
|
343
|
+
strategy: performanceStrategy,
|
|
344
|
+
},
|
|
656
345
|
});
|
|
657
346
|
```
|
|
658
347
|
|
|
@@ -667,7 +356,7 @@ Wayfinder includes verification mechanisms to ensure the integrity of retrieved
|
|
|
667
356
|
| `DataRootVerificationStrategy` | Medium | Medium | Low | Computes the data root for the transaction (most useful for L1 transactions) and compares it to the data root provided by a **trusted gateway**. |
|
|
668
357
|
| `SignatureVerificationStrategy` | Medium | Medium | Medium | - **ANS-104 Data Items**: Fetches signature components (owner, signature type, tags, etc.) from trusted gateways using range requests, then verifies signatures against the data payload using deep hash calculations following the ANS-104 standard.<br/>- **L1 Transactions**: Retrieves transaction metadata from gateway /tx/<tx-id> endpoints, computes the data root from the provided data stream, and verifies the signature using Arweave's cryptographic verification. |
|
|
669
358
|
|
|
670
|
-
|
|
359
|
+
#### RemoteVerificationStrategy
|
|
671
360
|
|
|
672
361
|
This strategy is used to verify data by checking the `x-ar-io-verified` header from the gateway that returned the data. If the header is set to `true`, the data is considered verified and trusted.
|
|
673
362
|
|
|
@@ -686,7 +375,7 @@ const wayfinder = new Wayfinder({
|
|
|
686
375
|
});
|
|
687
376
|
```
|
|
688
377
|
|
|
689
|
-
|
|
378
|
+
#### HashVerificationStrategy
|
|
690
379
|
|
|
691
380
|
Verifies data integrity using SHA-256 hash comparison. This is the default verification strategy and is recommended for most users looking for a balance between security and performance.
|
|
692
381
|
|
|
@@ -703,7 +392,7 @@ const wayfinder = new Wayfinder({
|
|
|
703
392
|
});
|
|
704
393
|
```
|
|
705
394
|
|
|
706
|
-
|
|
395
|
+
#### DataRootVerificationStrategy
|
|
707
396
|
|
|
708
397
|
Verifies data integrity using Arweave by computing the data root for the transaction. This is useful for L1 transactions and is recommended for users who want to ensure the integrity of their data.
|
|
709
398
|
|
|
@@ -720,7 +409,7 @@ const wayfinder = new Wayfinder({
|
|
|
720
409
|
});
|
|
721
410
|
```
|
|
722
411
|
|
|
723
|
-
|
|
412
|
+
#### SignatureVerificationStrategy
|
|
724
413
|
|
|
725
414
|
Verifies signatures of Arweave transactions and data items. Headers are retrieved from trusted gateways for use during verification. For a transaction, its data root is computed while streaming its data and then utilized alongside its headers for verification. For data items, the ANS-104 deep hash method of signature verification is used.
|
|
726
415
|
|
|
@@ -737,229 +426,89 @@ const wayfinder = new Wayfinder({
|
|
|
737
426
|
});
|
|
738
427
|
```
|
|
739
428
|
|
|
740
|
-
##
|
|
429
|
+
## x402 Payments
|
|
741
430
|
|
|
742
|
-
|
|
431
|
+
Wayfinder can be configured to work with the [x402 payment protocol](https://docs.ar.io/learn/gateways/x402-payments#what-is-x402) for paid gateway services and higher rate limits. This allows you to seamlessly make requests that may require payment without having to manually handle payment flows.
|
|
743
432
|
|
|
744
|
-
|
|
433
|
+
> [!IMPORTANT]
|
|
434
|
+
> To use x402 payments, you need to install the `@ar.io/wayfinder-x402-fetch` package.
|
|
745
435
|
|
|
746
436
|
```javascript
|
|
747
|
-
|
|
748
|
-
|
|
437
|
+
import { createWayfinderClient } from '@ar.io/wayfinder-core';
|
|
438
|
+
import { createX402Fetch } from '@ar.io/wayfinder-x402-fetch';
|
|
439
|
+
import { privateKeyToAccount } from 'viem/accounts';
|
|
440
|
+
|
|
441
|
+
// Set up your wallet for x402 payments
|
|
442
|
+
const privateKey = process.env.X402_PRIVATE_KEY; // Your private key
|
|
443
|
+
const account = privateKeyToAccount(privateKey);
|
|
444
|
+
|
|
445
|
+
// Create x402-enabled fetch implementation
|
|
446
|
+
const x402Fetch = createX402Fetch({
|
|
447
|
+
walletClient: account,
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
// Create Wayfinder client with x402 fetch
|
|
451
|
+
const wayfinder = createWayfinderClient({
|
|
452
|
+
fetch: x402Fetch,
|
|
749
453
|
routingSettings: {
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
onRoutingSkipped: (event) => {
|
|
755
|
-
console.log('Routing skipped!', event);
|
|
756
|
-
},
|
|
757
|
-
onRoutingSucceeded: (event) => {
|
|
758
|
-
console.log('Routing succeeded!', event);
|
|
759
|
-
},
|
|
760
|
-
},
|
|
761
|
-
},
|
|
762
|
-
verificationSettings: {
|
|
763
|
-
events: {
|
|
764
|
-
onVerificationSucceeded: (event) => {
|
|
765
|
-
console.log(`Verification passed for transaction: ${event.txId}`);
|
|
766
|
-
},
|
|
767
|
-
onVerificationFailed: (event) => {
|
|
768
|
-
console.error(
|
|
769
|
-
`Verification failed for transaction: ${event.txId}`,
|
|
770
|
-
event.error,
|
|
771
|
-
);
|
|
772
|
-
},
|
|
773
|
-
onVerificationProgress: (event) => {
|
|
774
|
-
const percentage = (event.processedBytes / event.totalBytes) * 100;
|
|
775
|
-
console.log(
|
|
776
|
-
`Verification progress for ${event.txId}: ${percentage.toFixed(2)}%`,
|
|
777
|
-
);
|
|
778
|
-
},
|
|
779
|
-
},
|
|
454
|
+
// Configure to use x402-enabled gateways
|
|
455
|
+
strategy: new StaticRoutingStrategy({
|
|
456
|
+
gateway: 'https://paid-gateway.example.com',
|
|
457
|
+
}),
|
|
780
458
|
},
|
|
781
459
|
});
|
|
782
460
|
|
|
783
|
-
//
|
|
784
|
-
wayfinder.
|
|
785
|
-
|
|
786
|
-
});
|
|
461
|
+
// Requests will now automatically handle x402 payments
|
|
462
|
+
const response = await wayfinder.request('ar://transaction-id');
|
|
463
|
+
```
|
|
787
464
|
|
|
788
|
-
|
|
789
|
-
console.error(`Routing failed: ${event.error.message}`);
|
|
790
|
-
});
|
|
465
|
+
**How it works:**
|
|
791
466
|
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
467
|
+
1. When a gateway returns a `402 Payment Required` status
|
|
468
|
+
2. The x402 fetch automatically handles the payment flow
|
|
469
|
+
3. The request is retried with payment credentials
|
|
470
|
+
4. You get access to premium gateway services
|
|
795
471
|
|
|
796
|
-
|
|
797
|
-
console.log(`Verification succeeded: ${event.txId}`);
|
|
798
|
-
});
|
|
472
|
+
**Use cases:**
|
|
799
473
|
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
```
|
|
474
|
+
- Higher rate limits on data requests
|
|
475
|
+
- Access to premium gateway features
|
|
476
|
+
- Supporting gateway operators through payments
|
|
804
477
|
|
|
805
|
-
|
|
478
|
+
To learn more about x402 payments, visit the [x402 documentation](https://docs.ar.io/learn/gateways/x402-payments).
|
|
806
479
|
|
|
807
|
-
|
|
480
|
+
## Events and Monitoring
|
|
808
481
|
|
|
809
|
-
|
|
810
|
-
> Events are still emitted to the global event emitter for all requests. It is recommended to use the global event emitter for tracking all requests, and the request-specific events for tracking a single request.
|
|
482
|
+
#### Global Events
|
|
811
483
|
|
|
812
484
|
```javascript
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
verificationSettings: {
|
|
816
|
-
enabled: true,
|
|
817
|
-
strategy: new HashVerificationStrategy({
|
|
818
|
-
trustedGateways: ['https://permagate.io'],
|
|
819
|
-
}),
|
|
485
|
+
const wayfinder = createWayfinderClient({
|
|
486
|
+
routingSettings: {
|
|
820
487
|
events: {
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
},
|
|
824
|
-
onVerificationSucceeded: (event) => {
|
|
825
|
-
console.log(`Global callback handler called for: ${event.txId}`);
|
|
826
|
-
},
|
|
488
|
+
onRoutingStarted: (event) => console.log('Routing started:', event),
|
|
489
|
+
onRoutingSucceeded: (event) => console.log('Gateway selected:', event),
|
|
827
490
|
},
|
|
828
491
|
},
|
|
829
|
-
});
|
|
830
|
-
|
|
831
|
-
const response = await wayfinder.request('ar://example-name', {
|
|
832
492
|
verificationSettings: {
|
|
833
|
-
// these callbacks will be triggered for this request only, the global callback handlers are still called
|
|
834
493
|
events: {
|
|
835
494
|
onVerificationProgress: (event) => {
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
onVerificationSucceeded: (event) => {
|
|
839
|
-
console.log(`Request-specific callback handler called for: ${event.txId}`);
|
|
495
|
+
const percentage = (event.processedBytes / event.totalBytes) * 100;
|
|
496
|
+
console.log(`Verification: ${percentage.toFixed(2)}%`);
|
|
840
497
|
},
|
|
498
|
+
onVerificationSucceeded: (event) => console.log('Verified:', event.txId),
|
|
841
499
|
},
|
|
842
500
|
},
|
|
843
501
|
});
|
|
844
502
|
```
|
|
845
503
|
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
### Optional Dependencies
|
|
849
|
-
|
|
850
|
-
The `@ar.io/sdk` package is an optional peer dependency. To use AR.IO network gateways, instantiate a `NetworkGatewaysProvider` with an `ario` instance and supply it to `Wayfinder` directly:
|
|
851
|
-
|
|
852
|
-
**With AR.IO SDK (Recommended):**
|
|
853
|
-
```bash
|
|
854
|
-
npm install @ar.io/wayfinder-core @ar.io/sdk
|
|
855
|
-
# or
|
|
856
|
-
yarn add @ar.io/wayfinder-core @ar.io/sdk
|
|
857
|
-
```
|
|
858
|
-
- `new NetworkGatewaysProvider({ ario: ARIO.mainnet() })` exposes AR.IO network gateways
|
|
859
|
-
- Supports intelligent gateway selection criteria
|
|
860
|
-
- Dynamic gateway discovery and updates
|
|
861
|
-
|
|
862
|
-
### Caching
|
|
863
|
-
|
|
864
|
-
Wayfinder supports intelligent caching:
|
|
865
|
-
|
|
866
|
-
- **In browsers**: Uses localStorage for persistent caching across page reloads
|
|
867
|
-
- **In Node.js**: Uses in-memory caching
|
|
868
|
-
- **What's cached**: Gateway lists, routing decisions, and more
|
|
869
|
-
- **Cache configuration**:
|
|
870
|
-
- `cache: true` - Enable with default 5-minute TTL
|
|
871
|
-
- `cache: { ttlSeconds: 3600 }` - Enable with custom TTL (in seconds)
|
|
872
|
-
- `cache: false` - Disable caching (default)
|
|
873
|
-
|
|
874
|
-
## Advanced Usage
|
|
875
|
-
|
|
876
|
-
### Custom Providers and Strategies
|
|
877
|
-
|
|
878
|
-
For advanced use cases, provide strategy instances explicitly:
|
|
504
|
+
#### Request-Specific Events
|
|
879
505
|
|
|
880
506
|
```javascript
|
|
881
|
-
|
|
882
|
-
createWayfinderClient,
|
|
883
|
-
FastestPingRoutingStrategy,
|
|
884
|
-
HashVerificationStrategy,
|
|
885
|
-
} from '@ar.io/wayfinder-core';
|
|
886
|
-
|
|
887
|
-
const wayfinder = createWayfinderClient({
|
|
888
|
-
// Enable caching with custom TTL
|
|
889
|
-
cache: { ttlSeconds: 3600 }, // 1 hour
|
|
890
|
-
|
|
891
|
-
// Supply a bespoke routing strategy
|
|
892
|
-
routingStrategy: new FastestPingRoutingStrategy({
|
|
893
|
-
timeoutMs: 1000,
|
|
894
|
-
}),
|
|
895
|
-
|
|
896
|
-
// Configure verification explicitly
|
|
897
|
-
verificationStrategy: new HashVerificationStrategy({
|
|
898
|
-
trustedGateways: [new URL('https://permagate.io')],
|
|
899
|
-
}),
|
|
900
|
-
});
|
|
901
|
-
```
|
|
902
|
-
|
|
903
|
-
### Direct Constructor Usage
|
|
904
|
-
|
|
905
|
-
For complete control, you can use the Wayfinder constructor directly. This is useful when you need fine-grained control over the configuration:
|
|
906
|
-
|
|
907
|
-
> _Wayfinder client that caches the top 10 gateways by operator stake from the ARIO Network for 1 hour and uses the fastest pinging routing strategy to select the fastest gateway for requests._
|
|
908
|
-
|
|
909
|
-
```javascript
|
|
910
|
-
import { Wayfinder, NetworkGatewaysProvider, SimpleCacheGatewaysProvider, FastestPingRoutingStrategy, HashVerificationStrategy } from '@ar.io/wayfinder-core';
|
|
911
|
-
import { ARIO } from '@ar.io/sdk';
|
|
912
|
-
|
|
913
|
-
const wayfinder = new Wayfinder({
|
|
914
|
-
// cache the top 10 gateways by operator stake from the ARIO Network for 1 hour
|
|
915
|
-
gatewaysProvider: new SimpleCacheGatewaysProvider({
|
|
916
|
-
ttlSeconds: 60 * 60, // cache the gateways for 1 hour
|
|
917
|
-
gatewaysProvider: new NetworkGatewaysProvider({
|
|
918
|
-
ario: ARIO.mainnet(),
|
|
919
|
-
sortBy: 'operatorStake',
|
|
920
|
-
sortOrder: 'desc',
|
|
921
|
-
limit: 10,
|
|
922
|
-
}),
|
|
923
|
-
}),
|
|
924
|
-
// routing settings
|
|
925
|
-
routingSettings: {
|
|
926
|
-
// use the fastest pinging strategy to select the fastest gateway for requests
|
|
927
|
-
strategy: new FastestPingRoutingStrategy({
|
|
928
|
-
timeoutMs: 1000,
|
|
929
|
-
}),
|
|
930
|
-
// events
|
|
931
|
-
events: {
|
|
932
|
-
onRoutingStarted: (event) => {
|
|
933
|
-
console.log('Routing started!', event);
|
|
934
|
-
},
|
|
935
|
-
onRoutingSkipped: (event) => {
|
|
936
|
-
console.log('Routing skipped!', event);
|
|
937
|
-
},
|
|
938
|
-
onRoutingSucceeded: (event) => {
|
|
939
|
-
console.log('Routing succeeded!', event);
|
|
940
|
-
},
|
|
941
|
-
},
|
|
942
|
-
},
|
|
943
|
-
// verification settings
|
|
507
|
+
const response = await wayfinder.request('ar://example', {
|
|
944
508
|
verificationSettings: {
|
|
945
|
-
// enable verification - if false, verification will be skipped for all requests
|
|
946
|
-
enabled: true,
|
|
947
|
-
// verify the data using the hash of the data against a list of trusted gateways
|
|
948
|
-
strategy: new HashVerificationStrategy({
|
|
949
|
-
trustedGateways: [new URL('https://permagate.io')],
|
|
950
|
-
}),
|
|
951
|
-
// strict verification - if true, verification failures will cause requests to fail
|
|
952
|
-
strict: true,
|
|
953
|
-
// events
|
|
954
509
|
events: {
|
|
955
510
|
onVerificationProgress: (event) => {
|
|
956
|
-
console.log(
|
|
957
|
-
},
|
|
958
|
-
onVerificationSucceeded: (event) => {
|
|
959
|
-
console.log('Verification succeeded!', event);
|
|
960
|
-
},
|
|
961
|
-
onVerificationFailed: (event) => {
|
|
962
|
-
console.log('Verification failed!', event);
|
|
511
|
+
console.log(`This request: ${event.txId}`);
|
|
963
512
|
},
|
|
964
513
|
},
|
|
965
514
|
},
|
|
@@ -970,26 +519,23 @@ const wayfinder = new Wayfinder({
|
|
|
970
519
|
|
|
971
520
|
Wayfinder can optionally emit OpenTelemetry spans for every request. **By default, telemetry is disabled**. You can control this behavior with the `telemetry` option.
|
|
972
521
|
|
|
973
|
-
```
|
|
974
|
-
|
|
522
|
+
```typescript
|
|
975
523
|
import { createWayfinderClient } from '@ar.io/wayfinder-core';
|
|
976
524
|
|
|
977
525
|
const wayfinder = createWayfinderClient({
|
|
978
526
|
// other settings...
|
|
979
|
-
|
|
980
|
-
enabled: true,
|
|
981
|
-
sampleRate: 0.1, // 10%
|
|
982
|
-
exporterUrl: 'https://your-
|
|
983
|
-
clientName: 'my-
|
|
984
|
-
clientVersion: '1.0.0',
|
|
527
|
+
telemetrySettings: {
|
|
528
|
+
enabled: true,
|
|
529
|
+
sampleRate: 0.1, // 10% sampling
|
|
530
|
+
exporterUrl: 'https://your-otel-exporter',
|
|
531
|
+
clientName: 'my-app',
|
|
532
|
+
clientVersion: '1.0.0',
|
|
985
533
|
},
|
|
986
534
|
});
|
|
987
535
|
```
|
|
988
536
|
|
|
989
537
|
## Request Flow
|
|
990
538
|
|
|
991
|
-
The following sequence diagram illustrates how Wayfinder processes requests:
|
|
992
|
-
|
|
993
539
|
```mermaid
|
|
994
540
|
sequenceDiagram
|
|
995
541
|
participant Client
|
|
@@ -1006,27 +552,19 @@ sequenceDiagram
|
|
|
1006
552
|
Wayfinder->>+Gateways Provider: getGateways()
|
|
1007
553
|
Gateways Provider-->>-Wayfinder: List of gateway URLs
|
|
1008
554
|
|
|
1009
|
-
Wayfinder->>+Routing Strategy: selectGateway()
|
|
1010
|
-
Routing Strategy-->>-Wayfinder:
|
|
1011
|
-
|
|
1012
|
-
Wayfinder->>+Selected Gateway:
|
|
1013
|
-
Selected Gateway-->>-Wayfinder: Response
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
Verification Strategy->>Verification Strategy: Compare computed vs trusted data
|
|
1021
|
-
Verification Strategy-->>-Wayfinder: Return request data with verification result
|
|
1022
|
-
|
|
1023
|
-
alt Verification passed
|
|
1024
|
-
Wayfinder->>Wayfinder: Emit 'verification-passed' event
|
|
1025
|
-
Wayfinder-->>Client: Return verified response
|
|
1026
|
-
else Verification failed
|
|
1027
|
-
Wayfinder->>Wayfinder: Emit 'verification-failed' event
|
|
1028
|
-
Wayfinder-->>Client: Throw verification error
|
|
555
|
+
Wayfinder->>+Routing Strategy: selectGateway()
|
|
556
|
+
Routing Strategy-->>-Wayfinder: Selected gateway
|
|
557
|
+
|
|
558
|
+
Wayfinder->>+Selected Gateway: HTTP request
|
|
559
|
+
Selected Gateway-->>-Wayfinder: Response data
|
|
560
|
+
|
|
561
|
+
opt Verification enabled
|
|
562
|
+
Wayfinder->>+Verification Strategy: verifyData()
|
|
563
|
+
Verification Strategy->>Trusted Gateways: Get verification data
|
|
564
|
+
Trusted Gateways-->>Verification Strategy: Verification headers
|
|
565
|
+
Verification Strategy-->>-Wayfinder: Verification result
|
|
1029
566
|
end
|
|
1030
567
|
|
|
568
|
+
Wayfinder-->>Client: Response or error
|
|
1031
569
|
deactivate Wayfinder
|
|
1032
570
|
```
|