@ar.io/sdk 3.13.0-beta.1 → 3.14.0-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 +1 -1
- package/bundles/web.bundle.min.js +133 -136
- package/lib/cjs/cli/cli.js +8 -0
- package/lib/cjs/common/ant.js +102 -1
- package/lib/cjs/common/index.js +0 -2
- package/lib/cjs/utils/ant.js +32 -1
- package/lib/cjs/utils/hash.js +31 -83
- package/lib/cjs/version.js +1 -1
- package/lib/esm/cli/cli.js +8 -0
- package/lib/esm/common/ant.js +103 -2
- package/lib/esm/common/index.js +0 -2
- package/lib/esm/utils/ant.js +30 -0
- package/lib/esm/utils/hash.js +27 -74
- package/lib/esm/version.js +1 -1
- package/lib/types/common/ant.d.ts +9 -1
- package/lib/types/common/index.d.ts +0 -1
- package/lib/types/types/ant.d.ts +17 -0
- package/lib/types/types/io.d.ts +0 -3
- package/lib/types/utils/ant.d.ts +7 -1
- package/lib/types/utils/hash.d.ts +4 -8
- package/lib/types/version.d.ts +1 -1
- package/package.json +1 -2
- package/lib/cjs/common/wayfinder/gateways/network.js +0 -48
- package/lib/cjs/common/wayfinder/gateways/simple-cache.js +0 -35
- package/lib/cjs/common/wayfinder/gateways/static.js +0 -13
- package/lib/cjs/common/wayfinder/index.js +0 -48
- package/lib/cjs/common/wayfinder/routing/strategies/ping.js +0 -72
- package/lib/cjs/common/wayfinder/routing/strategies/preferred-with-fallback.js +0 -50
- package/lib/cjs/common/wayfinder/routing/strategies/random.js +0 -13
- package/lib/cjs/common/wayfinder/routing/strategies/round-robin.js +0 -42
- package/lib/cjs/common/wayfinder/routing/strategies/static.js +0 -29
- package/lib/cjs/common/wayfinder/verification/strategies/data-root-verifier.js +0 -110
- package/lib/cjs/common/wayfinder/verification/strategies/hash-verifier.js +0 -27
- package/lib/cjs/common/wayfinder/verification/trusted.js +0 -125
- package/lib/cjs/common/wayfinder/wayfinder.js +0 -508
- package/lib/cjs/types/wayfinder.js +0 -3
- package/lib/esm/common/wayfinder/gateways/network.js +0 -44
- package/lib/esm/common/wayfinder/gateways/simple-cache.js +0 -31
- package/lib/esm/common/wayfinder/gateways/static.js +0 -9
- package/lib/esm/common/wayfinder/index.js +0 -32
- package/lib/esm/common/wayfinder/routing/strategies/ping.js +0 -68
- package/lib/esm/common/wayfinder/routing/strategies/preferred-with-fallback.js +0 -46
- package/lib/esm/common/wayfinder/routing/strategies/random.js +0 -9
- package/lib/esm/common/wayfinder/routing/strategies/round-robin.js +0 -38
- package/lib/esm/common/wayfinder/routing/strategies/static.js +0 -25
- package/lib/esm/common/wayfinder/verification/strategies/data-root-verifier.js +0 -102
- package/lib/esm/common/wayfinder/verification/strategies/hash-verifier.js +0 -23
- package/lib/esm/common/wayfinder/verification/trusted.js +0 -121
- package/lib/esm/common/wayfinder/wayfinder.js +0 -499
- package/lib/esm/types/wayfinder.js +0 -2
- package/lib/types/common/wayfinder/gateways/network.d.ts +0 -33
- package/lib/types/common/wayfinder/gateways/simple-cache.d.ts +0 -31
- package/lib/types/common/wayfinder/gateways/static.d.ts +0 -23
- package/lib/types/common/wayfinder/index.d.ts +0 -27
- package/lib/types/common/wayfinder/routing/strategies/ping.d.ts +0 -27
- package/lib/types/common/wayfinder/routing/strategies/preferred-with-fallback.d.ts +0 -31
- package/lib/types/common/wayfinder/routing/strategies/random.d.ts +0 -21
- package/lib/types/common/wayfinder/routing/strategies/round-robin.d.ts +0 -29
- package/lib/types/common/wayfinder/routing/strategies/static.d.ts +0 -29
- package/lib/types/common/wayfinder/verification/strategies/data-root-verifier.d.ts +0 -27
- package/lib/types/common/wayfinder/verification/strategies/hash-verifier.d.ts +0 -26
- package/lib/types/common/wayfinder/verification/trusted.d.ts +0 -51
- package/lib/types/common/wayfinder/wayfinder.d.ts +0 -257
- package/lib/types/types/wayfinder.d.ts +0 -66
|
@@ -1,499 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
|
|
3
|
-
*
|
|
4
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
* you may not use this file except in compliance with the License.
|
|
6
|
-
* You may obtain a copy of the License at
|
|
7
|
-
*
|
|
8
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
*
|
|
10
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
* See the License for the specific language governing permissions and
|
|
14
|
-
* limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
import { EventEmitter } from 'eventemitter3';
|
|
17
|
-
import { base32 } from 'rfc4648';
|
|
18
|
-
import { ARIO } from '../io.js';
|
|
19
|
-
import { Logger } from '../logger.js';
|
|
20
|
-
import { NetworkGatewaysProvider } from './gateways/network.js';
|
|
21
|
-
import { SimpleCacheGatewaysProvider } from './gateways/simple-cache.js';
|
|
22
|
-
import { StaticGatewaysProvider } from './gateways/static.js';
|
|
23
|
-
import { FastestPingRoutingStrategy } from './routing/strategies/ping.js';
|
|
24
|
-
import { HashVerificationStrategy } from './verification/strategies/hash-verifier.js';
|
|
25
|
-
import { TrustedGatewaysHashProvider } from './verification/trusted.js';
|
|
26
|
-
// known regexes for wayfinder urls
|
|
27
|
-
export const arnsRegex = /^[a-z0-9_-]{1,51}$/;
|
|
28
|
-
export const txIdRegex = /^[A-Za-z0-9_-]{43}$/;
|
|
29
|
-
/**
|
|
30
|
-
* Core function that converts a wayfinder url to the proper ar-io gateway URL
|
|
31
|
-
* @param originalUrl - the wayfinder url to resolve
|
|
32
|
-
* @param selectedGateway - the target gateway to resolve the url against
|
|
33
|
-
* @returns the resolved url that can be used to make a request
|
|
34
|
-
*/
|
|
35
|
-
export const resolveWayfinderUrl = ({ originalUrl, selectedGateway, logger, }) => {
|
|
36
|
-
if (originalUrl.toString().startsWith('ar://')) {
|
|
37
|
-
logger?.debug(`Applying wayfinder routing protocol to ${originalUrl}`, {
|
|
38
|
-
originalUrl,
|
|
39
|
-
});
|
|
40
|
-
const [, path] = originalUrl.toString().split('ar://');
|
|
41
|
-
// e.g. ar:///info should route to the info endpoint of the target gateway
|
|
42
|
-
if (path.startsWith('/')) {
|
|
43
|
-
logger?.debug(`Routing to ${path.slice(1)} on ${selectedGateway}`, {
|
|
44
|
-
originalUrl,
|
|
45
|
-
selectedGateway,
|
|
46
|
-
});
|
|
47
|
-
return new URL(path.slice(1), selectedGateway);
|
|
48
|
-
}
|
|
49
|
-
// Split path to get the first part (name/txId) and remaining path components
|
|
50
|
-
const [firstPart, ...rest] = path.split('/');
|
|
51
|
-
// TODO: this breaks 43 character named arns names - we should check a a local name cache list before resolving raw transaction ids
|
|
52
|
-
if (txIdRegex.test(firstPart)) {
|
|
53
|
-
const sandbox = sandboxFromId(firstPart);
|
|
54
|
-
return new URL(`${firstPart}${rest.length > 0 ? '/' + rest.join('/') : ''}`, `${selectedGateway.protocol}//${sandbox}.${selectedGateway.hostname}`);
|
|
55
|
-
}
|
|
56
|
-
if (arnsRegex.test(firstPart)) {
|
|
57
|
-
// TODO: tests to ensure arns names support query params and paths
|
|
58
|
-
const arnsUrl = `${selectedGateway.protocol}//${firstPart}.${selectedGateway.hostname}${selectedGateway.port ? `:${selectedGateway.port}` : ''}`;
|
|
59
|
-
logger?.debug(`Routing to ${path} on ${arnsUrl}`, {
|
|
60
|
-
originalUrl,
|
|
61
|
-
selectedGateway,
|
|
62
|
-
});
|
|
63
|
-
return new URL(rest.length > 0 ? rest.join('/') : '', arnsUrl);
|
|
64
|
-
}
|
|
65
|
-
// TODO: support .eth addresses
|
|
66
|
-
// TODO: "gasless" routing via DNS TXT records
|
|
67
|
-
}
|
|
68
|
-
logger?.debug('No wayfinder routing protocol applied', {
|
|
69
|
-
originalUrl,
|
|
70
|
-
});
|
|
71
|
-
// return the original url if it's not a wayfinder url
|
|
72
|
-
return new URL(originalUrl);
|
|
73
|
-
};
|
|
74
|
-
export class WayfinderEmitter extends EventEmitter {
|
|
75
|
-
constructor({ onVerificationSucceeded, onVerificationFailed, onVerificationProgress, } = {}) {
|
|
76
|
-
super();
|
|
77
|
-
if (onVerificationSucceeded) {
|
|
78
|
-
this.on('verification-succeeded', onVerificationSucceeded);
|
|
79
|
-
}
|
|
80
|
-
if (onVerificationFailed) {
|
|
81
|
-
this.on('verification-failed', onVerificationFailed);
|
|
82
|
-
}
|
|
83
|
-
if (onVerificationProgress) {
|
|
84
|
-
this.on('verification-progress', onVerificationProgress);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
export function tapAndVerifyReadableStream({ originalStream, contentLength, verifyData, txId, emitter, strict = false, }) {
|
|
89
|
-
if (originalStream instanceof ReadableStream &&
|
|
90
|
-
typeof originalStream.tee === 'function') {
|
|
91
|
-
/**
|
|
92
|
-
* NOTE: tee requires the streams both streams to be consumed, so we need to make sure we consume the client branch
|
|
93
|
-
* by the caller. This means when `request` is called, the client stream must be consumed by the caller via await request.text()
|
|
94
|
-
* for verification to complete.
|
|
95
|
-
*
|
|
96
|
-
* It is feasible to make the verification stream not to depend on the client branch being consumed, should the DX not be obvious.
|
|
97
|
-
*/
|
|
98
|
-
const [verifyBranch, clientBranch] = originalStream.tee();
|
|
99
|
-
// setup our promise to verify the data
|
|
100
|
-
const verificationPromise = verifyData({
|
|
101
|
-
data: verifyBranch,
|
|
102
|
-
txId,
|
|
103
|
-
});
|
|
104
|
-
let bytesProcessed = 0;
|
|
105
|
-
const reader = clientBranch.getReader();
|
|
106
|
-
const clientStreamWithVerification = new ReadableStream({
|
|
107
|
-
async pull(controller) {
|
|
108
|
-
const { done, value } = await reader.read();
|
|
109
|
-
if (done) {
|
|
110
|
-
if (strict) {
|
|
111
|
-
// in strict mode, we wait for verification to complete before closing the controller
|
|
112
|
-
try {
|
|
113
|
-
await verificationPromise;
|
|
114
|
-
emitter?.emit('verification-succeeded', { txId });
|
|
115
|
-
controller.close();
|
|
116
|
-
}
|
|
117
|
-
catch (err) {
|
|
118
|
-
// emit the verification failed event
|
|
119
|
-
emitter?.emit('verification-failed', err);
|
|
120
|
-
// In strict mode, we report the error to the client stream
|
|
121
|
-
controller.error(new Error('Verification failed', { cause: err }));
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
else {
|
|
125
|
-
// trigger the verification promise and emit events for the result
|
|
126
|
-
verificationPromise
|
|
127
|
-
.then(() => {
|
|
128
|
-
emitter?.emit('verification-succeeded', { txId });
|
|
129
|
-
})
|
|
130
|
-
.catch((error) => {
|
|
131
|
-
emitter?.emit('verification-failed', error);
|
|
132
|
-
});
|
|
133
|
-
// in non-strict mode, we close the controller immediately and handle verification asynchronously
|
|
134
|
-
controller.close();
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
else {
|
|
138
|
-
bytesProcessed += value.length;
|
|
139
|
-
emitter?.emit('verification-progress', {
|
|
140
|
-
txId,
|
|
141
|
-
totalBytes: contentLength,
|
|
142
|
-
processedBytes: bytesProcessed,
|
|
143
|
-
});
|
|
144
|
-
controller.enqueue(value);
|
|
145
|
-
}
|
|
146
|
-
},
|
|
147
|
-
cancel(reason) {
|
|
148
|
-
// cancel the reader regardless of verification status
|
|
149
|
-
reader.cancel(reason);
|
|
150
|
-
// emit the verification cancellation event
|
|
151
|
-
emitter?.emit('verification-failed', {
|
|
152
|
-
txId,
|
|
153
|
-
error: new Error('Verification cancelled', {
|
|
154
|
-
cause: {
|
|
155
|
-
reason,
|
|
156
|
-
},
|
|
157
|
-
}),
|
|
158
|
-
});
|
|
159
|
-
},
|
|
160
|
-
});
|
|
161
|
-
return clientStreamWithVerification;
|
|
162
|
-
}
|
|
163
|
-
throw new Error('Unsupported body type for cloning');
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* Gets the sandbox hash for a given transaction id
|
|
167
|
-
*/
|
|
168
|
-
export function sandboxFromId(id) {
|
|
169
|
-
return base32
|
|
170
|
-
.stringify(Buffer.from(id, 'base64'), { pad: false })
|
|
171
|
-
.toLowerCase();
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
* Creates a wrapped fetch function that supports ar:// protocol
|
|
175
|
-
*
|
|
176
|
-
* This function leverages a Proxy to intercept calls to fetch
|
|
177
|
-
* and redirects them to the target gateway using the resolveUrl function.
|
|
178
|
-
*
|
|
179
|
-
* Any URLs provided that are not wayfinder urls will be passed directly to fetch.
|
|
180
|
-
*
|
|
181
|
-
* @param resolveUrl - the function to construct the redirect url for ar:// requests
|
|
182
|
-
* @returns a wrapped fetch function that supports ar:// protocol and always returns Response
|
|
183
|
-
*/
|
|
184
|
-
export const createWayfinderClient = ({ resolveUrl, verifyData, selectGateway, emitter = new WayfinderEmitter(), logger, strict = false, }) => {
|
|
185
|
-
return async (url, init) => {
|
|
186
|
-
if (typeof url !== 'string') {
|
|
187
|
-
logger?.debug('URL is not a string, skipping routing', {
|
|
188
|
-
url,
|
|
189
|
-
});
|
|
190
|
-
emitter?.emit('routing-skipped', {
|
|
191
|
-
originalUrl: JSON.stringify(url),
|
|
192
|
-
});
|
|
193
|
-
return fetch(url, init);
|
|
194
|
-
}
|
|
195
|
-
emitter?.emit('routing-started', {
|
|
196
|
-
originalUrl: url.toString(),
|
|
197
|
-
});
|
|
198
|
-
const maxRetries = 3;
|
|
199
|
-
const retryDelay = 1000;
|
|
200
|
-
for (let i = 0; i < maxRetries; i++) {
|
|
201
|
-
try {
|
|
202
|
-
// select the target gateway
|
|
203
|
-
const selectedGateway = await selectGateway();
|
|
204
|
-
logger?.debug('Selected gateway', {
|
|
205
|
-
originalUrl: url,
|
|
206
|
-
selectedGateway: selectedGateway.toString(),
|
|
207
|
-
});
|
|
208
|
-
// route the request to the target gateway
|
|
209
|
-
const redirectUrl = resolveUrl({
|
|
210
|
-
originalUrl: url,
|
|
211
|
-
selectedGateway,
|
|
212
|
-
logger,
|
|
213
|
-
});
|
|
214
|
-
emitter?.emit('routing-succeeded', {
|
|
215
|
-
originalUrl: url,
|
|
216
|
-
selectedGateway: selectedGateway.toString(),
|
|
217
|
-
redirectUrl: redirectUrl.toString(),
|
|
218
|
-
});
|
|
219
|
-
logger?.debug(`Redirecting request`, {
|
|
220
|
-
originalUrl: url,
|
|
221
|
-
redirectUrl: redirectUrl.toString(),
|
|
222
|
-
});
|
|
223
|
-
// make the request to the target gateway using the redirect url
|
|
224
|
-
const response = await fetch(redirectUrl.toString(), {
|
|
225
|
-
// enforce CORS given we're likely going to a different origin, but always allow the client to override
|
|
226
|
-
redirect: 'follow',
|
|
227
|
-
mode: 'cors',
|
|
228
|
-
...init,
|
|
229
|
-
});
|
|
230
|
-
logger?.debug(`Successfully routed request to gateway`, {
|
|
231
|
-
redirectUrl: redirectUrl.toString(),
|
|
232
|
-
originalUrl: url.toString(),
|
|
233
|
-
});
|
|
234
|
-
// only verify data if the redirect url is different from the original url
|
|
235
|
-
if (redirectUrl.toString() !== url.toString()) {
|
|
236
|
-
if (verifyData) {
|
|
237
|
-
const headers = response.headers;
|
|
238
|
-
// transaction id is either in the response headers or the path of the request as the first parameter
|
|
239
|
-
const txId = headers.get('x-arns-resolved-id') ??
|
|
240
|
-
redirectUrl.pathname.split('/')[1];
|
|
241
|
-
const contentLength = +(headers.get('content-length') ?? 0);
|
|
242
|
-
if (!txIdRegex.test(txId)) {
|
|
243
|
-
// no transaction id found, skip verification
|
|
244
|
-
logger?.debug('No transaction id found, skipping verification', {
|
|
245
|
-
redirectUrl: redirectUrl.toString(),
|
|
246
|
-
originalUrl: url,
|
|
247
|
-
});
|
|
248
|
-
emitter?.emit('verification-skipped', {
|
|
249
|
-
originalUrl: url,
|
|
250
|
-
});
|
|
251
|
-
return response;
|
|
252
|
-
}
|
|
253
|
-
emitter?.emit('identified-transaction-id', {
|
|
254
|
-
originalUrl: url,
|
|
255
|
-
selectedGateway: redirectUrl.toString(),
|
|
256
|
-
txId,
|
|
257
|
-
});
|
|
258
|
-
// Check if the response has a body
|
|
259
|
-
if (response.body) {
|
|
260
|
-
const newClientStream = tapAndVerifyReadableStream({
|
|
261
|
-
originalStream: response.body,
|
|
262
|
-
contentLength,
|
|
263
|
-
verifyData,
|
|
264
|
-
txId,
|
|
265
|
-
emitter,
|
|
266
|
-
strict,
|
|
267
|
-
});
|
|
268
|
-
return new Response(newClientStream, {
|
|
269
|
-
status: response.status,
|
|
270
|
-
statusText: response.statusText,
|
|
271
|
-
headers: response.headers,
|
|
272
|
-
});
|
|
273
|
-
}
|
|
274
|
-
else {
|
|
275
|
-
// No response body to verify, skip verification
|
|
276
|
-
logger?.debug('No response body to verify', {
|
|
277
|
-
redirectUrl: redirectUrl.toString(),
|
|
278
|
-
originalUrl: url,
|
|
279
|
-
txId,
|
|
280
|
-
});
|
|
281
|
-
return response;
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
return response;
|
|
286
|
-
}
|
|
287
|
-
catch (error) {
|
|
288
|
-
logger?.debug('Failed to route request', {
|
|
289
|
-
error: error.message,
|
|
290
|
-
stack: error.stack,
|
|
291
|
-
originalUrl: url,
|
|
292
|
-
attempt: i + 1,
|
|
293
|
-
maxRetries,
|
|
294
|
-
});
|
|
295
|
-
if (i < maxRetries - 1) {
|
|
296
|
-
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
throw new Error('Failed to route request after max retries', {
|
|
301
|
-
cause: {
|
|
302
|
-
originalUrl: url,
|
|
303
|
-
maxRetries,
|
|
304
|
-
},
|
|
305
|
-
});
|
|
306
|
-
};
|
|
307
|
-
};
|
|
308
|
-
/**
|
|
309
|
-
* The main class for the wayfinder
|
|
310
|
-
*/
|
|
311
|
-
export class Wayfinder {
|
|
312
|
-
/**
|
|
313
|
-
* The gateways provider is responsible for providing the list of gateways to use for routing requests.
|
|
314
|
-
*
|
|
315
|
-
* @example
|
|
316
|
-
* const wayfinder = new Wayfinder({
|
|
317
|
-
* gatewaysProvider: new SimpleCacheGatewaysProvider({
|
|
318
|
-
* gatewaysProvider: new NetworkGatewaysProvider({ ario: ARIO.mainnet() }),
|
|
319
|
-
* ttlSeconds: 60 * 60 * 24, // 1 day
|
|
320
|
-
* }),
|
|
321
|
-
* });
|
|
322
|
-
*/
|
|
323
|
-
gatewaysProvider;
|
|
324
|
-
/**
|
|
325
|
-
* The routing strategy to use when routing requests.
|
|
326
|
-
*
|
|
327
|
-
* @example
|
|
328
|
-
* const wayfinder = new Wayfinder({
|
|
329
|
-
* strategy: new FastestPingStrategy({
|
|
330
|
-
* timeoutMs: 1000,
|
|
331
|
-
* }),
|
|
332
|
-
* });
|
|
333
|
-
*/
|
|
334
|
-
routingStrategy;
|
|
335
|
-
/**
|
|
336
|
-
* A helper function that resolves the redirect url for ar:// requests to a target gateway.
|
|
337
|
-
*
|
|
338
|
-
* Note: no verification is done when resolving an ar://<path> url to a wayfinder route.
|
|
339
|
-
* In order to verify the data, you must use the `request` function or request the data and
|
|
340
|
-
* verify it yourself via the `verifyData` function.
|
|
341
|
-
*
|
|
342
|
-
* @example
|
|
343
|
-
* const { resolveUrl } = new Wayfinder();
|
|
344
|
-
*
|
|
345
|
-
* // returns the redirected URL based on the routing strategy and the original url
|
|
346
|
-
* const redirectUrl = await resolveUrl({ originalUrl: 'ar://example' });
|
|
347
|
-
*
|
|
348
|
-
* window.open(redirectUrl.toString(), '_blank');
|
|
349
|
-
*/
|
|
350
|
-
resolveUrl;
|
|
351
|
-
/**
|
|
352
|
-
* A wrapped fetch function that supports ar:// protocol. If a verification strategy is provided,
|
|
353
|
-
* the request will be verified and events will be emitted as the request is processed.
|
|
354
|
-
*
|
|
355
|
-
* @example
|
|
356
|
-
* const wayfinder = new Wayfinder({
|
|
357
|
-
* verificationStrategy: new HashVerificationStrategy({
|
|
358
|
-
* trustedHashProvider: new TrustedGatewaysHashProvider({
|
|
359
|
-
* gatewaysProvider: new StaticGatewaysProvider({
|
|
360
|
-
* gateways: ['https://permagate.io'],
|
|
361
|
-
* }),
|
|
362
|
-
* }),
|
|
363
|
-
* }),
|
|
364
|
-
* })
|
|
365
|
-
*
|
|
366
|
-
* // request an arns name
|
|
367
|
-
* const response = await wayfinder.request('ar://ardrive')
|
|
368
|
-
*
|
|
369
|
-
* // request a transaction id
|
|
370
|
-
* const response = await wayfinder.request('ar://1234567890')
|
|
371
|
-
*
|
|
372
|
-
* // Set strict mode to true to make verification blocking
|
|
373
|
-
* const wayfinder = new Wayfinder({
|
|
374
|
-
* strict: true,
|
|
375
|
-
* });
|
|
376
|
-
*
|
|
377
|
-
* // This will throw an error if verification fails
|
|
378
|
-
* try {
|
|
379
|
-
* const response = await wayfinder.request('ar://1234567890');
|
|
380
|
-
* } catch (error) {
|
|
381
|
-
* console.error('Verification failed', error);
|
|
382
|
-
* }
|
|
383
|
-
*/
|
|
384
|
-
request;
|
|
385
|
-
/**
|
|
386
|
-
* The function that verifies the data hash for a given transaction id.
|
|
387
|
-
*
|
|
388
|
-
* @example
|
|
389
|
-
* const wayfinder = new Wayfinder({
|
|
390
|
-
* verifyData: (data, txId) => {
|
|
391
|
-
* // some custom verification logic
|
|
392
|
-
* return true;
|
|
393
|
-
* },
|
|
394
|
-
* });
|
|
395
|
-
*/
|
|
396
|
-
verifyData;
|
|
397
|
-
/**
|
|
398
|
-
* Whether verification should be strict (blocking) or not.
|
|
399
|
-
* If true, verification failures will cause requests to fail.
|
|
400
|
-
* If false, verification will be performed asynchronously and failures will only emit events.
|
|
401
|
-
*/
|
|
402
|
-
strict;
|
|
403
|
-
/**
|
|
404
|
-
* The event emitter for wayfinder that emits verification events.
|
|
405
|
-
*
|
|
406
|
-
* const wayfinder = new Wayfinder()
|
|
407
|
-
*
|
|
408
|
-
* wayfinder.emitter.on('verification-succeeded', (event) => {
|
|
409
|
-
* console.log('Verification passed!', event);
|
|
410
|
-
* })
|
|
411
|
-
*
|
|
412
|
-
* wayfinder.emitter.on('verification-failed', (event) => {
|
|
413
|
-
* console.log('Verification failed!', event);
|
|
414
|
-
* })
|
|
415
|
-
*
|
|
416
|
-
* or implement the events interface and pass it in, using callback functions
|
|
417
|
-
*
|
|
418
|
-
* const wayfinder = new Wayfinder({
|
|
419
|
-
* events: {
|
|
420
|
-
* onVerificationPassed: (event) => {
|
|
421
|
-
* console.log('Verification passed!', event);
|
|
422
|
-
* },
|
|
423
|
-
* onVerificationFailed: (event) => {
|
|
424
|
-
* console.log('Verification failed!', event);
|
|
425
|
-
* },
|
|
426
|
-
* onVerificationProgress: (event) => {
|
|
427
|
-
* console.log('Verification progress!', event);
|
|
428
|
-
* },
|
|
429
|
-
* }
|
|
430
|
-
* })
|
|
431
|
-
*
|
|
432
|
-
* const response = await wayfind('ar://example');
|
|
433
|
-
*/
|
|
434
|
-
emitter;
|
|
435
|
-
/**
|
|
436
|
-
* The constructor for the wayfinder
|
|
437
|
-
* @param routingStrategy - the routing strategy to use for requests
|
|
438
|
-
* @param verificationStrategy - the verification strategy to use for requests
|
|
439
|
-
* @param gatewaysProvider - the gateways provider to use for routing requests
|
|
440
|
-
* @param logger - the logger to use for logging
|
|
441
|
-
* @param strict - if true, verification will be blocking and will fail requests if verification fails; if false, verification will be non-blocking
|
|
442
|
-
*/
|
|
443
|
-
constructor({ logger = Logger.default, gatewaysProvider = new SimpleCacheGatewaysProvider({
|
|
444
|
-
gatewaysProvider: new NetworkGatewaysProvider({
|
|
445
|
-
ario: ARIO.mainnet(),
|
|
446
|
-
}),
|
|
447
|
-
ttlSeconds: 60 * 60, // 1 hour
|
|
448
|
-
}), routingStrategy = new FastestPingRoutingStrategy({
|
|
449
|
-
timeoutMs: 1000,
|
|
450
|
-
}), verificationStrategy = new HashVerificationStrategy({
|
|
451
|
-
trustedHashProvider: new TrustedGatewaysHashProvider({
|
|
452
|
-
gatewaysProvider: new StaticGatewaysProvider({
|
|
453
|
-
gateways: ['https://permagate.io'],
|
|
454
|
-
}),
|
|
455
|
-
}),
|
|
456
|
-
}), events = {
|
|
457
|
-
onVerificationSucceeded: (event) => {
|
|
458
|
-
logger.debug('Verification passed!', event);
|
|
459
|
-
},
|
|
460
|
-
onVerificationFailed: (event) => {
|
|
461
|
-
logger.error('Verification failed!', event);
|
|
462
|
-
},
|
|
463
|
-
onVerificationProgress: (event) => {
|
|
464
|
-
logger.debug('Verification progress!', event);
|
|
465
|
-
},
|
|
466
|
-
}, strict = false, } = {}) {
|
|
467
|
-
this.routingStrategy = routingStrategy;
|
|
468
|
-
this.gatewaysProvider = gatewaysProvider;
|
|
469
|
-
this.emitter = new WayfinderEmitter(events);
|
|
470
|
-
this.verifyData =
|
|
471
|
-
verificationStrategy.verifyData.bind(verificationStrategy);
|
|
472
|
-
this.strict = strict;
|
|
473
|
-
// top level function to easily resolve wayfinder urls using the routing strategy and gateways provider
|
|
474
|
-
this.resolveUrl = async ({ originalUrl, logger }) => {
|
|
475
|
-
const selectedGateway = await this.routingStrategy.selectGateway({
|
|
476
|
-
gateways: await this.gatewaysProvider.getGateways(),
|
|
477
|
-
});
|
|
478
|
-
return resolveWayfinderUrl({
|
|
479
|
-
originalUrl,
|
|
480
|
-
selectedGateway,
|
|
481
|
-
logger,
|
|
482
|
-
});
|
|
483
|
-
};
|
|
484
|
-
// create a wayfinder client with the routing strategy and gateways provider
|
|
485
|
-
this.request = createWayfinderClient({
|
|
486
|
-
selectGateway: async () => {
|
|
487
|
-
return this.routingStrategy.selectGateway({
|
|
488
|
-
gateways: await this.gatewaysProvider.getGateways(),
|
|
489
|
-
});
|
|
490
|
-
},
|
|
491
|
-
resolveUrl: resolveWayfinderUrl,
|
|
492
|
-
verifyData: this.verifyData,
|
|
493
|
-
emitter: this.emitter,
|
|
494
|
-
logger,
|
|
495
|
-
strict,
|
|
496
|
-
});
|
|
497
|
-
logger?.debug(`Wayfinder initialized with ${routingStrategy.constructor.name} routing strategy`);
|
|
498
|
-
}
|
|
499
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
|
|
3
|
-
*
|
|
4
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
* you may not use this file except in compliance with the License.
|
|
6
|
-
* You may obtain a copy of the License at
|
|
7
|
-
*
|
|
8
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
*
|
|
10
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
* See the License for the specific language governing permissions and
|
|
14
|
-
* limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
import { AoARIORead, AoGatewayWithAddress } from '../../../types/io.js';
|
|
17
|
-
import { GatewaysProvider } from '../../../types/wayfinder.js';
|
|
18
|
-
export declare class NetworkGatewaysProvider implements GatewaysProvider {
|
|
19
|
-
private ario;
|
|
20
|
-
private sortBy;
|
|
21
|
-
private sortOrder;
|
|
22
|
-
private limit;
|
|
23
|
-
private filter;
|
|
24
|
-
constructor({ ario, sortBy, sortOrder, limit, filter, }: {
|
|
25
|
-
ario?: AoARIORead;
|
|
26
|
-
sortBy?: 'totalDelegatedStake' | 'operatorStake' | 'startTimestamp';
|
|
27
|
-
sortOrder?: 'asc' | 'desc';
|
|
28
|
-
limit?: number;
|
|
29
|
-
blocklist?: string[];
|
|
30
|
-
filter?: (gateway: AoGatewayWithAddress) => boolean;
|
|
31
|
-
});
|
|
32
|
-
getGateways(): Promise<URL[]>;
|
|
33
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
|
|
3
|
-
*
|
|
4
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
* you may not use this file except in compliance with the License.
|
|
6
|
-
* You may obtain a copy of the License at
|
|
7
|
-
*
|
|
8
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
*
|
|
10
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
* See the License for the specific language governing permissions and
|
|
14
|
-
* limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
import { GatewaysProvider } from '../../../types/wayfinder.js';
|
|
17
|
-
import { Logger } from '../../../web/index.js';
|
|
18
|
-
export declare class SimpleCacheGatewaysProvider implements GatewaysProvider {
|
|
19
|
-
private gatewaysProvider;
|
|
20
|
-
private ttlSeconds;
|
|
21
|
-
private lastUpdated;
|
|
22
|
-
private gatewaysCache;
|
|
23
|
-
private logger;
|
|
24
|
-
constructor({ gatewaysProvider, ttlSeconds, // 1 hour
|
|
25
|
-
logger, }: {
|
|
26
|
-
gatewaysProvider: GatewaysProvider;
|
|
27
|
-
ttlSeconds?: number;
|
|
28
|
-
logger?: Logger;
|
|
29
|
-
});
|
|
30
|
-
getGateways(): Promise<URL[]>;
|
|
31
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
|
|
3
|
-
*
|
|
4
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
* you may not use this file except in compliance with the License.
|
|
6
|
-
* You may obtain a copy of the License at
|
|
7
|
-
*
|
|
8
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
*
|
|
10
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
* See the License for the specific language governing permissions and
|
|
14
|
-
* limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
import { GatewaysProvider } from '../../../types/wayfinder.js';
|
|
17
|
-
export declare class StaticGatewaysProvider implements GatewaysProvider {
|
|
18
|
-
private gateways;
|
|
19
|
-
constructor({ gateways }: {
|
|
20
|
-
gateways: string[];
|
|
21
|
-
});
|
|
22
|
-
getGateways(): Promise<URL[]>;
|
|
23
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
|
|
3
|
-
*
|
|
4
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
* you may not use this file except in compliance with the License.
|
|
6
|
-
* You may obtain a copy of the License at
|
|
7
|
-
*
|
|
8
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
*
|
|
10
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
* See the License for the specific language governing permissions and
|
|
14
|
-
* limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
export * from './wayfinder.js';
|
|
17
|
-
export * from './routing/strategies/random.js';
|
|
18
|
-
export * from './routing/strategies/static.js';
|
|
19
|
-
export * from './routing/strategies/ping.js';
|
|
20
|
-
export * from './routing/strategies/round-robin.js';
|
|
21
|
-
export * from './routing/strategies/preferred-with-fallback.js';
|
|
22
|
-
export * from './gateways/network.js';
|
|
23
|
-
export * from './gateways/simple-cache.js';
|
|
24
|
-
export * from './gateways/static.js';
|
|
25
|
-
export * from './verification/trusted.js';
|
|
26
|
-
export * from './verification/strategies/data-root-verifier.js';
|
|
27
|
-
export * from './verification/strategies/hash-verifier.js';
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
|
|
3
|
-
*
|
|
4
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
* you may not use this file except in compliance with the License.
|
|
6
|
-
* You may obtain a copy of the License at
|
|
7
|
-
*
|
|
8
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
*
|
|
10
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
* See the License for the specific language governing permissions and
|
|
14
|
-
* limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
import { RoutingStrategy } from '../../../../types/wayfinder.js';
|
|
17
|
-
export declare class FastestPingRoutingStrategy implements RoutingStrategy {
|
|
18
|
-
private timeoutMs;
|
|
19
|
-
private probePath;
|
|
20
|
-
constructor({ timeoutMs, probePath, }?: {
|
|
21
|
-
timeoutMs?: number;
|
|
22
|
-
probePath?: string;
|
|
23
|
-
});
|
|
24
|
-
selectGateway({ gateways }: {
|
|
25
|
-
gateways: URL[];
|
|
26
|
-
}): Promise<URL>;
|
|
27
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
|
|
3
|
-
*
|
|
4
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
* you may not use this file except in compliance with the License.
|
|
6
|
-
* You may obtain a copy of the License at
|
|
7
|
-
*
|
|
8
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
*
|
|
10
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
* See the License for the specific language governing permissions and
|
|
14
|
-
* limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
import { RoutingStrategy } from '../../../../types/wayfinder.js';
|
|
17
|
-
import { Logger } from '../../../logger.js';
|
|
18
|
-
export declare class PreferredWithFallbackRoutingStrategy implements RoutingStrategy {
|
|
19
|
-
readonly name = "preferred-with-fallback";
|
|
20
|
-
private preferredGateway;
|
|
21
|
-
private fallbackStrategy;
|
|
22
|
-
private logger;
|
|
23
|
-
constructor({ preferredGateway, fallbackStrategy, logger, }: {
|
|
24
|
-
preferredGateway: string;
|
|
25
|
-
fallbackStrategy?: RoutingStrategy;
|
|
26
|
-
logger?: Logger;
|
|
27
|
-
});
|
|
28
|
-
selectGateway({ gateways }: {
|
|
29
|
-
gateways: URL[];
|
|
30
|
-
}): Promise<URL>;
|
|
31
|
-
}
|