@ar.io/sdk 3.11.0-alpha.5 → 3.11.0-alpha.7
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/bundles/web.bundle.min.js +61 -61
- package/lib/cjs/common/io.js +12 -3
- package/lib/cjs/common/wayfinder/gateways.js +19 -8
- package/lib/cjs/common/wayfinder/index.js +1 -1
- package/lib/cjs/common/wayfinder/routers/priority.js +11 -20
- package/lib/cjs/common/wayfinder/routers/priority.test.js +5 -5
- package/lib/cjs/common/wayfinder/routers/random.js +2 -2
- package/lib/cjs/common/wayfinder/routers/random.test.js +5 -84
- package/lib/cjs/common/wayfinder/routers/{fixed.js → static.js} +5 -5
- package/lib/cjs/common/wayfinder/routers/{fixed.test.js → static.test.js} +4 -4
- package/lib/cjs/common/wayfinder/wayfinder.js +2 -2
- package/lib/cjs/common/wayfinder/wayfinder.test.js +36 -48
- package/lib/cjs/utils/arweave.js +1 -1
- package/lib/cjs/version.js +1 -1
- package/lib/esm/common/io.js +12 -3
- package/lib/esm/common/wayfinder/gateways.js +17 -6
- package/lib/esm/common/wayfinder/index.js +1 -1
- package/lib/esm/common/wayfinder/routers/priority.js +11 -20
- package/lib/esm/common/wayfinder/routers/priority.test.js +5 -5
- package/lib/esm/common/wayfinder/routers/random.js +2 -2
- package/lib/esm/common/wayfinder/routers/random.test.js +5 -84
- package/lib/esm/common/wayfinder/routers/{fixed.js → static.js} +3 -3
- package/lib/esm/common/wayfinder/routers/{fixed.test.js → static.test.js} +4 -4
- package/lib/esm/common/wayfinder/wayfinder.js +3 -3
- package/lib/esm/common/wayfinder/wayfinder.test.js +36 -48
- package/lib/esm/utils/arweave.js +1 -1
- package/lib/esm/version.js +1 -1
- package/lib/types/common/io.d.ts +2 -6
- package/lib/types/common/wayfinder/gateways.d.ts +16 -7
- package/lib/types/common/wayfinder/index.d.ts +1 -1
- package/lib/types/common/wayfinder/routers/priority.d.ts +8 -12
- package/lib/types/common/wayfinder/routers/{fixed.d.ts → static.d.ts} +3 -3
- package/lib/types/version.d.ts +1 -1
- package/package.json +1 -1
- package/lib/cjs/cli/wayfinder.js +0 -34
- package/lib/esm/cli/wayfinder.js +0 -32
- package/lib/types/common/wayfinder/routers/fixed.test.d.ts +0 -1
- /package/lib/types/{cli/wayfinder.d.ts → common/wayfinder/routers/static.test.d.ts} +0 -0
|
@@ -1,7 +1,15 @@
|
|
|
1
|
-
export class
|
|
1
|
+
export class NetworkGatewaysProvider {
|
|
2
2
|
ario;
|
|
3
|
-
|
|
3
|
+
sortBy;
|
|
4
|
+
sortOrder;
|
|
5
|
+
limit;
|
|
6
|
+
filter;
|
|
7
|
+
constructor({ ario, sortBy = 'operatorStake', sortOrder = 'desc', limit = 1000, filter = (g) => g.status === 'joined', }) {
|
|
4
8
|
this.ario = ario;
|
|
9
|
+
this.sortBy = sortBy;
|
|
10
|
+
this.sortOrder = sortOrder;
|
|
11
|
+
this.limit = limit;
|
|
12
|
+
this.filter = filter;
|
|
5
13
|
}
|
|
6
14
|
async getGateways() {
|
|
7
15
|
let cursor;
|
|
@@ -9,9 +17,11 @@ export class ARIOGatewaysProvider {
|
|
|
9
17
|
const gateways = [];
|
|
10
18
|
do {
|
|
11
19
|
try {
|
|
12
|
-
const { items: newGateways, nextCursor } = await this.ario.getGateways({
|
|
20
|
+
const { items: newGateways = [], nextCursor } = await this.ario.getGateways({
|
|
13
21
|
limit: 1000,
|
|
14
22
|
cursor,
|
|
23
|
+
sortBy: this.sortBy,
|
|
24
|
+
sortOrder: this.sortOrder,
|
|
15
25
|
});
|
|
16
26
|
gateways.push(...newGateways);
|
|
17
27
|
cursor = nextCursor;
|
|
@@ -27,13 +37,14 @@ export class ARIOGatewaysProvider {
|
|
|
27
37
|
}
|
|
28
38
|
} while (cursor !== undefined && attempts < 3);
|
|
29
39
|
// filter out any gateways that are not joined
|
|
30
|
-
|
|
40
|
+
const filteredGateways = gateways.filter(this.filter).slice(0, this.limit);
|
|
41
|
+
return filteredGateways.map((g) => new URL(`${g.settings.protocol}://${g.settings.fqdn}:${g.settings.port}`));
|
|
31
42
|
}
|
|
32
43
|
}
|
|
33
44
|
export class StaticGatewaysProvider {
|
|
34
45
|
gateways;
|
|
35
46
|
constructor({ gateways }) {
|
|
36
|
-
this.gateways = gateways;
|
|
47
|
+
this.gateways = gateways.map((g) => new URL(g));
|
|
37
48
|
}
|
|
38
49
|
async getGateways() {
|
|
39
50
|
return this.gateways;
|
|
@@ -57,7 +68,7 @@ export class SimpleCacheGatewaysProvider {
|
|
|
57
68
|
try {
|
|
58
69
|
// preserve the cache if the fetch fails
|
|
59
70
|
const allGateways = await this.gatewaysProvider.getGateways();
|
|
60
|
-
this.gatewaysCache = allGateways
|
|
71
|
+
this.gatewaysCache = allGateways;
|
|
61
72
|
this.lastUpdated = now;
|
|
62
73
|
}
|
|
63
74
|
catch (error) {
|
|
@@ -17,6 +17,6 @@ export * from './wayfinder.js';
|
|
|
17
17
|
// routers
|
|
18
18
|
export * from './routers/random.js';
|
|
19
19
|
export * from './routers/priority.js';
|
|
20
|
-
export * from './routers/
|
|
20
|
+
export * from './routers/static.js';
|
|
21
21
|
// gateways providers
|
|
22
22
|
export * from './gateways.js';
|
|
@@ -1,34 +1,25 @@
|
|
|
1
1
|
import { randomInt } from '../../../utils/random.js';
|
|
2
|
+
import { NetworkGatewaysProvider } from '../gateways.js';
|
|
2
3
|
// TODO: one of N where N are in the last time window have met certain performance thresholds
|
|
3
4
|
// TODO: look at bitorrent routing protocols for inspiration
|
|
4
5
|
// TODO: router that looks at local stats/metrics and adjusts based on those
|
|
5
6
|
export class PriorityGatewayRouter {
|
|
6
7
|
name = 'priority';
|
|
7
8
|
gatewaysProvider;
|
|
8
|
-
limit
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
this.sortBy = sortBy;
|
|
16
|
-
this.sortOrder = sortOrder;
|
|
17
|
-
this.blocklist = blocklist;
|
|
9
|
+
constructor({ ario, sortBy, sortOrder, limit, }) {
|
|
10
|
+
this.gatewaysProvider = new NetworkGatewaysProvider({
|
|
11
|
+
ario,
|
|
12
|
+
sortBy,
|
|
13
|
+
sortOrder,
|
|
14
|
+
limit,
|
|
15
|
+
});
|
|
18
16
|
}
|
|
19
17
|
async getTargetGateway() {
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
!this.blocklist.includes(gateway.settings.fqdn));
|
|
23
|
-
const sortedGateways = gateways
|
|
24
|
-
.sort(this.sortOrder === 'asc'
|
|
25
|
-
? (a, b) => a[this.sortBy] - b[this.sortBy]
|
|
26
|
-
: (a, b) => b[this.sortBy] - a[this.sortBy])
|
|
27
|
-
.slice(0, this.limit);
|
|
28
|
-
const targetGateway = sortedGateways[randomInt(0, sortedGateways.length)];
|
|
18
|
+
const gateways = await this.gatewaysProvider.getGateways();
|
|
19
|
+
const targetGateway = gateways[randomInt(0, gateways.length)];
|
|
29
20
|
if (targetGateway === undefined) {
|
|
30
21
|
throw new Error('No target gateway found');
|
|
31
22
|
}
|
|
32
|
-
return
|
|
23
|
+
return targetGateway;
|
|
33
24
|
}
|
|
34
25
|
}
|
|
@@ -127,13 +127,13 @@ describe('PriorityRouter', () => {
|
|
|
127
127
|
},
|
|
128
128
|
},
|
|
129
129
|
];
|
|
130
|
-
const
|
|
131
|
-
getGateways: async () => mockGateways,
|
|
130
|
+
const mockArIOClient = {
|
|
131
|
+
getGateways: async () => ({ items: mockGateways }),
|
|
132
132
|
};
|
|
133
133
|
it('should prioritize gateway with highest success rate when using successRate weight', async () => {
|
|
134
134
|
const router = new PriorityGatewayRouter({
|
|
135
|
-
|
|
136
|
-
sortBy: '
|
|
135
|
+
ario: mockArIOClient,
|
|
136
|
+
sortBy: 'operatorStake',
|
|
137
137
|
sortOrder: 'desc',
|
|
138
138
|
limit: 1,
|
|
139
139
|
});
|
|
@@ -142,7 +142,7 @@ describe('PriorityRouter', () => {
|
|
|
142
142
|
});
|
|
143
143
|
it('should prioritize gateway with lowest latency when using latency weight', async () => {
|
|
144
144
|
const router = new PriorityGatewayRouter({
|
|
145
|
-
|
|
145
|
+
ario: mockArIOClient,
|
|
146
146
|
sortBy: 'operatorStake',
|
|
147
147
|
sortOrder: 'desc',
|
|
148
148
|
limit: 1,
|
|
@@ -9,11 +9,11 @@ export class RandomGatewayRouter {
|
|
|
9
9
|
}
|
|
10
10
|
async getTargetGateway() {
|
|
11
11
|
const allGateways = await this.gatewaysProvider.getGateways();
|
|
12
|
-
const gateways = allGateways.filter((g) =>
|
|
12
|
+
const gateways = allGateways.filter((g) => !this.blocklist.includes(g.hostname));
|
|
13
13
|
const targetGateway = gateways[randomInt(0, gateways.length)];
|
|
14
14
|
if (targetGateway === undefined) {
|
|
15
15
|
throw new Error('No target gateway found');
|
|
16
16
|
}
|
|
17
|
-
return
|
|
17
|
+
return targetGateway;
|
|
18
18
|
}
|
|
19
19
|
}
|
|
@@ -3,88 +3,9 @@ import { describe, it } from 'node:test';
|
|
|
3
3
|
import { RandomGatewayRouter } from './random.js';
|
|
4
4
|
describe('RandomRouter', () => {
|
|
5
5
|
const mockGateways = [
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
port: 443,
|
|
10
|
-
protocol: 'https',
|
|
11
|
-
allowDelegatedStaking: false,
|
|
12
|
-
delegateRewardShareRatio: 0.5,
|
|
13
|
-
allowedDelegates: [],
|
|
14
|
-
minDelegatedStake: 0,
|
|
15
|
-
autoStake: false,
|
|
16
|
-
properties: '',
|
|
17
|
-
label: '',
|
|
18
|
-
note: '',
|
|
19
|
-
},
|
|
20
|
-
gatewayAddress: 'addr1',
|
|
21
|
-
observerAddress: 'addr1',
|
|
22
|
-
totalDelegatedStake: 1000,
|
|
23
|
-
startTimestamp: 0,
|
|
24
|
-
endTimestamp: 0,
|
|
25
|
-
operatorStake: 100,
|
|
26
|
-
status: 'joined',
|
|
27
|
-
weights: {
|
|
28
|
-
normalizedCompositeWeight: 0.5,
|
|
29
|
-
stakeWeight: 0.5,
|
|
30
|
-
tenureWeight: 0.5,
|
|
31
|
-
gatewayPerformanceRatio: 0.5,
|
|
32
|
-
observerPerformanceRatio: 0.5,
|
|
33
|
-
compositeWeight: 0.5,
|
|
34
|
-
gatewayRewardRatioWeight: 0.5,
|
|
35
|
-
observerRewardRatioWeight: 0.5,
|
|
36
|
-
},
|
|
37
|
-
stats: {
|
|
38
|
-
passedConsecutiveEpochs: 10,
|
|
39
|
-
failedConsecutiveEpochs: 5,
|
|
40
|
-
totalEpochCount: 15,
|
|
41
|
-
passedEpochCount: 10,
|
|
42
|
-
failedEpochCount: 5,
|
|
43
|
-
observedEpochCount: 15,
|
|
44
|
-
prescribedEpochCount: 20,
|
|
45
|
-
},
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
settings: {
|
|
49
|
-
fqdn: 'gateway2.net',
|
|
50
|
-
port: 443,
|
|
51
|
-
protocol: 'https',
|
|
52
|
-
allowDelegatedStaking: false,
|
|
53
|
-
delegateRewardShareRatio: 0.5,
|
|
54
|
-
allowedDelegates: [],
|
|
55
|
-
minDelegatedStake: 0,
|
|
56
|
-
autoStake: false,
|
|
57
|
-
properties: '',
|
|
58
|
-
label: '',
|
|
59
|
-
note: '',
|
|
60
|
-
},
|
|
61
|
-
gatewayAddress: 'addr2',
|
|
62
|
-
observerAddress: 'addr2',
|
|
63
|
-
totalDelegatedStake: 0,
|
|
64
|
-
startTimestamp: 0,
|
|
65
|
-
endTimestamp: 0,
|
|
66
|
-
operatorStake: 0,
|
|
67
|
-
status: 'leaving',
|
|
68
|
-
weights: {
|
|
69
|
-
normalizedCompositeWeight: 0.5,
|
|
70
|
-
stakeWeight: 0.5,
|
|
71
|
-
tenureWeight: 0.5,
|
|
72
|
-
gatewayPerformanceRatio: 0.5,
|
|
73
|
-
observerPerformanceRatio: 0.5,
|
|
74
|
-
compositeWeight: 0.5,
|
|
75
|
-
gatewayRewardRatioWeight: 0.5,
|
|
76
|
-
observerRewardRatioWeight: 0.5,
|
|
77
|
-
},
|
|
78
|
-
stats: {
|
|
79
|
-
passedConsecutiveEpochs: 10,
|
|
80
|
-
failedConsecutiveEpochs: 5,
|
|
81
|
-
totalEpochCount: 15,
|
|
82
|
-
passedEpochCount: 10,
|
|
83
|
-
failedEpochCount: 5,
|
|
84
|
-
observedEpochCount: 15,
|
|
85
|
-
prescribedEpochCount: 20,
|
|
86
|
-
},
|
|
87
|
-
},
|
|
6
|
+
new URL('https://gateway1.net'),
|
|
7
|
+
new URL('https://gateway2.net'),
|
|
8
|
+
new URL('https://gateway3.net'),
|
|
88
9
|
];
|
|
89
10
|
const mockGatewaysProvider = {
|
|
90
11
|
getGateways: async () => mockGateways,
|
|
@@ -93,10 +14,10 @@ describe('RandomRouter', () => {
|
|
|
93
14
|
const router = new RandomGatewayRouter({
|
|
94
15
|
gatewaysProvider: mockGatewaysProvider,
|
|
95
16
|
});
|
|
96
|
-
//
|
|
17
|
+
// random gateway should be one of the mock gateways
|
|
97
18
|
for (let i = 0; i < 10; i++) {
|
|
98
19
|
const result = await router.getTargetGateway();
|
|
99
|
-
assert.
|
|
20
|
+
assert.ok(mockGateways.includes(result));
|
|
100
21
|
}
|
|
101
22
|
});
|
|
102
23
|
});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export class
|
|
2
|
-
name = '
|
|
1
|
+
export class StaticGatewayRouter {
|
|
2
|
+
name = 'static';
|
|
3
3
|
gateway;
|
|
4
4
|
constructor({ gateway }) {
|
|
5
|
-
this.gateway = gateway;
|
|
5
|
+
this.gateway = new URL(gateway);
|
|
6
6
|
}
|
|
7
7
|
async getTargetGateway() {
|
|
8
8
|
return this.gateway;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { strict as assert } from 'node:assert';
|
|
2
2
|
import { describe, it } from 'node:test';
|
|
3
|
-
import {
|
|
4
|
-
describe('
|
|
3
|
+
import { StaticGatewayRouter } from './static.js';
|
|
4
|
+
describe('StaticGatewayRouter', () => {
|
|
5
5
|
it('should return the provided gateway', async () => {
|
|
6
|
-
const router = new
|
|
7
|
-
gateway:
|
|
6
|
+
const router = new StaticGatewayRouter({
|
|
7
|
+
gateway: 'http://test-gateway.net',
|
|
8
8
|
});
|
|
9
9
|
const result = await router.getTargetGateway();
|
|
10
10
|
assert.deepStrictEqual(result, new URL('http://test-gateway.net'));
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { ARIO } from '../io.js';
|
|
2
2
|
import { Logger } from '../logger.js';
|
|
3
|
-
import {
|
|
3
|
+
import { NetworkGatewaysProvider } from './gateways.js';
|
|
4
4
|
import { RandomGatewayRouter } from './routers/random.js';
|
|
5
5
|
// known regexes for wayfinder urls
|
|
6
6
|
export const arnsRegex = /^[a-z0-9_-]{1,51}$/;
|
|
7
|
-
export const txIdRegex = /^[
|
|
7
|
+
export const txIdRegex = /^[A-Za-z0-9_-]{43}$/;
|
|
8
8
|
/**
|
|
9
9
|
* Core function to resolve a wayfinder url against a target gateway
|
|
10
10
|
* @param originalUrl - the wayfinder url to resolve
|
|
@@ -176,7 +176,7 @@ export class Wayfinder {
|
|
|
176
176
|
// TODO: consider changing router to routingStrategy or strategy
|
|
177
177
|
router = new RandomGatewayRouter({
|
|
178
178
|
// optionally use a cache gateways provider to reduce the number of requests to the contract
|
|
179
|
-
gatewaysProvider: new
|
|
179
|
+
gatewaysProvider: new NetworkGatewaysProvider({ ario: ARIO.mainnet() }),
|
|
180
180
|
}), httpClient, logger = Logger.default,
|
|
181
181
|
// TODO: add verifier interface that provides a verifyDataHash function
|
|
182
182
|
// TODO: stats provider
|
|
@@ -3,23 +3,14 @@ import got from 'got';
|
|
|
3
3
|
import assert from 'node:assert';
|
|
4
4
|
import { buffer } from 'node:stream/consumers';
|
|
5
5
|
import { before, describe, it } from 'node:test';
|
|
6
|
+
import { Logger } from '../../common/logger.js';
|
|
6
7
|
import { RandomGatewayRouter } from './routers/random.js';
|
|
7
8
|
import { Wayfinder } from './wayfinder.js';
|
|
8
|
-
const
|
|
9
|
-
status: 'joined',
|
|
10
|
-
gatewayAddress: 'arweave',
|
|
11
|
-
operatorStake: 1000,
|
|
12
|
-
totalDelegatedStake: 1000,
|
|
13
|
-
startTimestamp: 1000,
|
|
14
|
-
settings: {
|
|
15
|
-
protocol: 'https',
|
|
16
|
-
fqdn: 'arweave.net',
|
|
17
|
-
port: 443,
|
|
18
|
-
},
|
|
19
|
-
};
|
|
9
|
+
const gatewayUrl = 'permagate.io';
|
|
20
10
|
const stubbedGatewaysProvider = {
|
|
21
|
-
getGateways: async () => [
|
|
11
|
+
getGateways: async () => [new URL(`https://${gatewayUrl}`)],
|
|
22
12
|
};
|
|
13
|
+
Logger.default.setLogLevel('debug');
|
|
23
14
|
describe('Wayfinder', () => {
|
|
24
15
|
describe('http wrapper', () => {
|
|
25
16
|
describe('fetch', () => {
|
|
@@ -33,7 +24,7 @@ describe('Wayfinder', () => {
|
|
|
33
24
|
});
|
|
34
25
|
});
|
|
35
26
|
it('should fetch the data using the selected gateway', async () => {
|
|
36
|
-
const nativeFetch = await fetch(
|
|
27
|
+
const nativeFetch = await fetch(`https://ao.${gatewayUrl}`);
|
|
37
28
|
const response = await wayfinder.request('ar://ao');
|
|
38
29
|
assert.strictEqual(response.status, 200);
|
|
39
30
|
assert.strictEqual(response.status, nativeFetch.status);
|
|
@@ -41,44 +32,48 @@ describe('Wayfinder', () => {
|
|
|
41
32
|
const arnsHeaders = Array.from(response.headers.entries()).filter(([key]) => key.startsWith('x-arns-'));
|
|
42
33
|
const nativeFetchHeaders = Array.from(nativeFetch.headers.entries()).filter(([key]) => key.startsWith('x-arns-'));
|
|
43
34
|
assert.deepStrictEqual(arnsHeaders, nativeFetchHeaders);
|
|
44
|
-
|
|
35
|
+
});
|
|
36
|
+
it('should fetch a tx id using the selected gateway', async () => {
|
|
37
|
+
const nativeFetch = await fetch(`https://${gatewayUrl}/KKmRbIfrc7wiLcG0zvY1etlO0NBx1926dSCksxCIN3A`,
|
|
38
|
+
// follow redirects
|
|
39
|
+
{ redirect: 'follow' });
|
|
40
|
+
const response = await wayfinder.request('ar://KKmRbIfrc7wiLcG0zvY1etlO0NBx1926dSCksxCIN3A', { redirect: 'follow' });
|
|
41
|
+
assert.strictEqual(response.status, 200);
|
|
42
|
+
assert.strictEqual(response.status, nativeFetch.status);
|
|
45
43
|
});
|
|
46
44
|
it('should route a non-ar:// url as a normal fetch', async () => {
|
|
47
45
|
const [nativeFetch, response] = await Promise.all([
|
|
48
|
-
fetch(
|
|
46
|
+
fetch(`https://${gatewayUrl}/`, {
|
|
49
47
|
method: 'HEAD',
|
|
50
48
|
}),
|
|
51
|
-
wayfinder.request(
|
|
49
|
+
wayfinder.request(`https://${gatewayUrl}/`, {
|
|
52
50
|
method: 'HEAD',
|
|
53
51
|
}),
|
|
54
52
|
]);
|
|
55
53
|
assert.strictEqual(response.status, 200);
|
|
56
54
|
assert.strictEqual(response.status, nativeFetch.status);
|
|
57
55
|
// TODO: ensure the headers are the same excluding unique headers
|
|
58
|
-
assert.deepStrictEqual(await response.text(), await nativeFetch.text());
|
|
59
56
|
});
|
|
60
|
-
for (const api of ['/info', '/
|
|
57
|
+
for (const api of ['/info', '/block/current']) {
|
|
61
58
|
it(`supports native arweave node apis ${api}`, async () => {
|
|
62
59
|
const [nativeFetch, response] = await Promise.all([
|
|
63
|
-
fetch(`https
|
|
64
|
-
wayfinder.request(`ar
|
|
60
|
+
fetch(`https://${gatewayUrl}${api}`),
|
|
61
|
+
wayfinder.request(`ar://${api}`),
|
|
65
62
|
]);
|
|
66
63
|
assert.strictEqual(response.status, 200);
|
|
67
64
|
assert.strictEqual(response.status, nativeFetch.status);
|
|
68
65
|
// TODO: ensure the headers are the same excluding unique headers
|
|
69
|
-
assert.deepStrictEqual(await response.text(), await nativeFetch.text());
|
|
70
66
|
});
|
|
71
67
|
}
|
|
72
|
-
for (const api of ['/ar-io/info'
|
|
68
|
+
for (const api of ['/ar-io/info']) {
|
|
73
69
|
it(`supports native ario node gateway apis ${api}`, async () => {
|
|
74
70
|
const [nativeFetch, response] = await Promise.all([
|
|
75
|
-
fetch(`https
|
|
71
|
+
fetch(`https://${gatewayUrl}${api}`),
|
|
76
72
|
wayfinder.request(`ar:///${api}`),
|
|
77
73
|
]);
|
|
78
74
|
assert.strictEqual(response.status, 200);
|
|
79
75
|
assert.strictEqual(response.status, nativeFetch.status);
|
|
80
76
|
// TODO: ensure the headers are the same excluding unique headers
|
|
81
|
-
assert.deepStrictEqual(await response.text(), await nativeFetch.text());
|
|
82
77
|
});
|
|
83
78
|
}
|
|
84
79
|
it('supports a post request to graphql', async () => {
|
|
@@ -117,14 +112,13 @@ describe('Wayfinder', () => {
|
|
|
117
112
|
});
|
|
118
113
|
assert.strictEqual(response.status, 200);
|
|
119
114
|
});
|
|
120
|
-
it('returns the error from the target gateway if the route is not found', async () => {
|
|
115
|
+
it.skip('returns the error from the target gateway if the route is not found', async () => {
|
|
121
116
|
const [nativeFetch, response] = await Promise.all([
|
|
122
|
-
fetch(
|
|
123
|
-
wayfinder.request('
|
|
117
|
+
fetch(`https://${gatewayUrl}/ar-io/not-found`),
|
|
118
|
+
wayfinder.request('ar:///not-found'),
|
|
124
119
|
]);
|
|
125
120
|
assert.strictEqual(response.status, nativeFetch.status);
|
|
126
121
|
assert.strictEqual(response.statusText, nativeFetch.statusText);
|
|
127
|
-
assert.deepStrictEqual(await response.text(), await nativeFetch.text());
|
|
128
122
|
});
|
|
129
123
|
});
|
|
130
124
|
describe('axios', () => {
|
|
@@ -139,7 +133,7 @@ describe('Wayfinder', () => {
|
|
|
139
133
|
});
|
|
140
134
|
it('should fetch the data using axios default function against the target gateway', async () => {
|
|
141
135
|
const [nativeAxios, response] = await Promise.all([
|
|
142
|
-
axios(
|
|
136
|
+
axios(`https://ao.${gatewayUrl}`),
|
|
143
137
|
wayfinder.request('ar://ao'),
|
|
144
138
|
]);
|
|
145
139
|
assert.strictEqual(response.status, 200);
|
|
@@ -150,11 +144,10 @@ describe('Wayfinder', () => {
|
|
|
150
144
|
.filter(([key]) => key.startsWith('x-arns-'));
|
|
151
145
|
const nativeAxiosHeaders = Object.entries(nativeAxios.headers).filter(([key]) => key.startsWith('x-arns-'));
|
|
152
146
|
assert.deepStrictEqual(arnsHeaders.sort(), nativeAxiosHeaders.sort());
|
|
153
|
-
assert.deepStrictEqual(response.data, nativeAxios.data);
|
|
154
147
|
});
|
|
155
148
|
it('should fetch the data using the axios.get method against the target gateway', async () => {
|
|
156
149
|
const [nativeAxios, response] = await Promise.all([
|
|
157
|
-
axios.get(
|
|
150
|
+
axios.get(`https://ao.${gatewayUrl}`),
|
|
158
151
|
wayfinder.request.get('ar://ao'),
|
|
159
152
|
]);
|
|
160
153
|
assert.strictEqual(response.status, 200);
|
|
@@ -165,43 +158,39 @@ describe('Wayfinder', () => {
|
|
|
165
158
|
.filter(([key]) => key.startsWith('x-arns-'));
|
|
166
159
|
const nativeAxiosHeaders = Object.entries(nativeAxios.headers).filter(([key]) => key.startsWith('x-arns-'));
|
|
167
160
|
assert.deepStrictEqual(arnsHeaders.sort(), nativeAxiosHeaders.sort());
|
|
168
|
-
assert.deepStrictEqual(response.data, nativeAxios.data);
|
|
169
161
|
});
|
|
170
162
|
it('should route a non-ar:// url as a normal axios request', async () => {
|
|
171
163
|
const [nativeAxios, response] = await Promise.all([
|
|
172
|
-
axios(
|
|
173
|
-
wayfinder.request(
|
|
164
|
+
axios(`https://${gatewayUrl}/`),
|
|
165
|
+
wayfinder.request(`https://${gatewayUrl}/`),
|
|
174
166
|
]);
|
|
175
167
|
assert.strictEqual(response.status, 200);
|
|
176
168
|
assert.strictEqual(response.status, nativeAxios.status);
|
|
177
|
-
assert.deepStrictEqual(response.data, nativeAxios.data);
|
|
178
169
|
// TODO: ensure the headers are the same excluding unique headers
|
|
179
170
|
});
|
|
180
|
-
for (const api of ['/info', '/
|
|
171
|
+
for (const api of ['/info', '/block/current']) {
|
|
181
172
|
it(`supports native arweave node apis ${api}`, async () => {
|
|
182
173
|
const [nativeAxios, response] = await Promise.all([
|
|
183
|
-
axios(`https
|
|
184
|
-
wayfinder.request(`ar
|
|
174
|
+
axios(`https://${gatewayUrl}${api}`),
|
|
175
|
+
wayfinder.request(`ar://${api}`),
|
|
185
176
|
]);
|
|
186
177
|
assert.strictEqual(response.status, 200);
|
|
187
178
|
assert.strictEqual(response.status, nativeAxios.status);
|
|
188
179
|
// TODO: ensure the headers are the same excluding unique headers
|
|
189
|
-
assert.deepStrictEqual(response.data, nativeAxios.data);
|
|
190
180
|
});
|
|
191
181
|
}
|
|
192
182
|
for (const api of ['/ar-io/info', '/ar-io/__gateway_metrics']) {
|
|
193
183
|
it(`supports native ario node gateway apis ${api}`, async () => {
|
|
194
184
|
const [nativeAxios, response] = await Promise.all([
|
|
195
|
-
axios(`https
|
|
185
|
+
axios(`https://${gatewayUrl}${api}`),
|
|
196
186
|
wayfinder.request(`ar:///${api}`),
|
|
197
187
|
]);
|
|
198
188
|
assert.strictEqual(response.status, 200);
|
|
199
189
|
assert.strictEqual(response.status, nativeAxios.status);
|
|
200
190
|
// TODO: ensure the headers are the same excluding unique headers
|
|
201
|
-
assert.deepStrictEqual(response.data, nativeAxios.data);
|
|
202
191
|
});
|
|
203
192
|
}
|
|
204
|
-
it('should return the error from the target gateway if the route is not found', async () => {
|
|
193
|
+
it.skip('should return the error from the target gateway if the route is not found', async () => {
|
|
205
194
|
const axiosInstance = axios.create({
|
|
206
195
|
validateStatus: () => true, // don't throw so we can compare axios result with wrapped axios result
|
|
207
196
|
});
|
|
@@ -212,11 +201,10 @@ describe('Wayfinder', () => {
|
|
|
212
201
|
}),
|
|
213
202
|
});
|
|
214
203
|
const [nativeAxios, response] = await Promise.all([
|
|
215
|
-
axiosInstance(
|
|
216
|
-
wayfinder.request('
|
|
204
|
+
axiosInstance(`https://${gatewayUrl}/ar-io/not-found`),
|
|
205
|
+
wayfinder.request('ar:///not-found'),
|
|
217
206
|
]);
|
|
218
207
|
assert.strictEqual(response.status, nativeAxios.status);
|
|
219
|
-
assert.strictEqual(response.data, nativeAxios.data);
|
|
220
208
|
});
|
|
221
209
|
});
|
|
222
210
|
describe('got', () => {
|
|
@@ -231,7 +219,7 @@ describe('Wayfinder', () => {
|
|
|
231
219
|
});
|
|
232
220
|
it('should fetch the data using the got default function against the target gateway', async () => {
|
|
233
221
|
const [nativeGot, response] = await Promise.all([
|
|
234
|
-
got(
|
|
222
|
+
got(`https://ao.${gatewayUrl}`),
|
|
235
223
|
wayfinder.request('ar://ao'),
|
|
236
224
|
]);
|
|
237
225
|
assert.strictEqual(response.statusCode, 200);
|
|
@@ -239,7 +227,7 @@ describe('Wayfinder', () => {
|
|
|
239
227
|
assert.deepStrictEqual(response.body, nativeGot.body);
|
|
240
228
|
});
|
|
241
229
|
it('should stream the data using got.stream against the selected target gateway', async () => {
|
|
242
|
-
const nativeBuffer = await buffer(await got.stream(
|
|
230
|
+
const nativeBuffer = await buffer(await got.stream(`https://ao.${gatewayUrl}`, { decompress: false }));
|
|
243
231
|
const wayfinderBuffer = await buffer(await wayfinder.request.stream('ar://ao', { decompress: false }));
|
|
244
232
|
assert.deepStrictEqual(wayfinderBuffer, nativeBuffer);
|
|
245
233
|
});
|
package/lib/esm/utils/arweave.js
CHANGED
|
@@ -107,7 +107,7 @@ export const getEpochDataFromGqlFallback = async ({ ao, epochIndex, processId =
|
|
|
107
107
|
if (!messageResult) {
|
|
108
108
|
continue;
|
|
109
109
|
}
|
|
110
|
-
for (const message of messageResult
|
|
110
|
+
for (const message of messageResult?.Messages ?? []) {
|
|
111
111
|
const data = JSON.parse(message.Data);
|
|
112
112
|
const tags = message.Tags;
|
|
113
113
|
// check if the message results include epoch-distribution-notice for the requested epoch index
|
package/lib/esm/version.js
CHANGED
package/lib/types/common/io.d.ts
CHANGED
|
@@ -9,12 +9,8 @@ export declare class ARIO {
|
|
|
9
9
|
static init(config: ARIOConfigWithSigner): AoARIOWrite;
|
|
10
10
|
static init(config: ARIOConfigNoSigner): AoARIORead;
|
|
11
11
|
static mainnet(): AoARIORead;
|
|
12
|
-
static mainnet(config: ARIOConfigNoSigner
|
|
13
|
-
|
|
14
|
-
}): AoARIORead;
|
|
15
|
-
static mainnet(config: ARIOConfigWithSigner & {
|
|
16
|
-
faucetUrl?: string;
|
|
17
|
-
}): AoARIOWrite;
|
|
12
|
+
static mainnet(config: ARIOConfigNoSigner): AoARIORead;
|
|
13
|
+
static mainnet(config: ARIOConfigWithSigner): AoARIOWrite;
|
|
18
14
|
static testnet(): ARIOWithFaucet<AoARIORead>;
|
|
19
15
|
static testnet(config: ARIOConfigNoSigner & {
|
|
20
16
|
faucetUrl?: string;
|
|
@@ -15,21 +15,30 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { AoARIORead, AoGatewayWithAddress } from '../../types/io.js';
|
|
17
17
|
export interface GatewaysProvider {
|
|
18
|
-
getGateways(): Promise<
|
|
18
|
+
getGateways(): Promise<URL[]>;
|
|
19
19
|
}
|
|
20
|
-
export declare class
|
|
20
|
+
export declare class NetworkGatewaysProvider implements GatewaysProvider {
|
|
21
21
|
private ario;
|
|
22
|
-
|
|
22
|
+
private sortBy;
|
|
23
|
+
private sortOrder;
|
|
24
|
+
private limit;
|
|
25
|
+
private filter;
|
|
26
|
+
constructor({ ario, sortBy, sortOrder, limit, filter, }: {
|
|
23
27
|
ario: AoARIORead;
|
|
28
|
+
sortBy?: 'totalDelegatedStake' | 'operatorStake' | 'startTimestamp';
|
|
29
|
+
sortOrder?: 'asc' | 'desc';
|
|
30
|
+
limit?: number;
|
|
31
|
+
blocklist?: string[];
|
|
32
|
+
filter?: (gateway: AoGatewayWithAddress) => boolean;
|
|
24
33
|
});
|
|
25
|
-
getGateways(): Promise<
|
|
34
|
+
getGateways(): Promise<URL[]>;
|
|
26
35
|
}
|
|
27
36
|
export declare class StaticGatewaysProvider implements GatewaysProvider {
|
|
28
37
|
private gateways;
|
|
29
38
|
constructor({ gateways }: {
|
|
30
|
-
gateways:
|
|
39
|
+
gateways: string[];
|
|
31
40
|
});
|
|
32
|
-
getGateways(): Promise<
|
|
41
|
+
getGateways(): Promise<URL[]>;
|
|
33
42
|
}
|
|
34
43
|
export declare class SimpleCacheGatewaysProvider implements GatewaysProvider {
|
|
35
44
|
private gatewaysProvider;
|
|
@@ -40,5 +49,5 @@ export declare class SimpleCacheGatewaysProvider implements GatewaysProvider {
|
|
|
40
49
|
gatewaysProvider: GatewaysProvider;
|
|
41
50
|
ttlSeconds?: number;
|
|
42
51
|
});
|
|
43
|
-
getGateways(): Promise<
|
|
52
|
+
getGateways(): Promise<URL[]>;
|
|
44
53
|
}
|
|
@@ -14,20 +14,16 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
import { WayfinderRouter } from '../../../types/wayfinder.js';
|
|
17
|
-
import {
|
|
17
|
+
import { AoARIORead } from '../../../web/index.js';
|
|
18
|
+
import { NetworkGatewaysProvider } from '../gateways.js';
|
|
18
19
|
export declare class PriorityGatewayRouter implements WayfinderRouter {
|
|
19
20
|
readonly name = "priority";
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
gatewaysProvider: GatewaysProvider;
|
|
27
|
-
limit?: number;
|
|
28
|
-
sortBy?: 'totalDelegatedStake' | 'operatorStake' | 'startTimestamp';
|
|
29
|
-
sortOrder?: 'asc' | 'desc';
|
|
30
|
-
blocklist?: string[];
|
|
21
|
+
readonly gatewaysProvider: NetworkGatewaysProvider;
|
|
22
|
+
constructor({ ario, sortBy, sortOrder, limit, }: {
|
|
23
|
+
ario: AoARIORead;
|
|
24
|
+
sortBy: 'operatorStake' | 'totalDelegatedStake' | 'startTimestamp';
|
|
25
|
+
sortOrder: 'asc' | 'desc';
|
|
26
|
+
limit: number;
|
|
31
27
|
});
|
|
32
28
|
getTargetGateway(): Promise<URL>;
|
|
33
29
|
}
|