@gearbox-protocol/sdk 9.0.4 → 9.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/dev/RevolverTransport.js +195 -0
- package/dist/cjs/dev/index.js +4 -2
- package/dist/cjs/dev/{createTransport.js → providers.js} +3 -33
- package/dist/esm/dev/RevolverTransport.js +177 -0
- package/dist/esm/dev/index.js +2 -1
- package/dist/esm/dev/{createTransport.js → providers.js} +0 -29
- package/dist/types/dev/RevolverTransport.d.ts +77 -0
- package/dist/types/dev/index.d.ts +2 -1
- package/dist/types/dev/{createTransport.d.ts → providers.d.ts} +2 -8
- package/package.json +1 -1
- package/dist/types/sdk/chain/detectNetwork.test.d.ts +0 -1
- package/dist/types/sdk/market/pricefeeds/updates/RedstoneUpdater.test.d.ts +0 -1
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var RevolverTransport_exports = {};
|
|
20
|
+
__export(RevolverTransport_exports, {
|
|
21
|
+
NoAvailableTransportsError: () => NoAvailableTransportsError,
|
|
22
|
+
RevolverTransport: () => RevolverTransport
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(RevolverTransport_exports);
|
|
25
|
+
var import_viem = require("viem");
|
|
26
|
+
var import_providers = require("./providers.js");
|
|
27
|
+
class NoAvailableTransportsError extends import_viem.BaseError {
|
|
28
|
+
constructor() {
|
|
29
|
+
super("no available transports");
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
class RevolverTransport {
|
|
33
|
+
#transports;
|
|
34
|
+
#index = 0;
|
|
35
|
+
#config;
|
|
36
|
+
overrides;
|
|
37
|
+
/**
|
|
38
|
+
* Create a new RevolverTransport
|
|
39
|
+
* RevolverTransport usues several RPC providers and rotates between them when requests fail
|
|
40
|
+
* Failed transport goes into temporary cooldown, after which it can be tried again
|
|
41
|
+
* When all transports are on cooldown, the transport will throw a NoAvailableTransportsError
|
|
42
|
+
* @param config
|
|
43
|
+
* @returns
|
|
44
|
+
*/
|
|
45
|
+
static create(config) {
|
|
46
|
+
const transport = new RevolverTransport({
|
|
47
|
+
...config
|
|
48
|
+
});
|
|
49
|
+
return (...args) => {
|
|
50
|
+
transport.overrides = args[0];
|
|
51
|
+
return transport;
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
constructor(config) {
|
|
55
|
+
this.#config = { ...config };
|
|
56
|
+
const rpcUrls = /* @__PURE__ */ new Map();
|
|
57
|
+
const cooldowns = /* @__PURE__ */ new Map();
|
|
58
|
+
for (const { provider, keys, cooldown } of config.providers) {
|
|
59
|
+
for (const key of keys) {
|
|
60
|
+
const url = (0, import_providers.getProviderUrl)(provider, config.network, key, "http");
|
|
61
|
+
if (url) {
|
|
62
|
+
rpcUrls.set(url, provider);
|
|
63
|
+
if (cooldown) {
|
|
64
|
+
cooldowns.set(url, cooldown);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
this.#transports = Array.from(rpcUrls.entries()).map(
|
|
70
|
+
([url, provider], i) => ({
|
|
71
|
+
provider,
|
|
72
|
+
transport: (0, import_viem.http)(url, {
|
|
73
|
+
retryCount: config.retryCount,
|
|
74
|
+
retryDelay: config.retryDelay,
|
|
75
|
+
timeout: config.timeout,
|
|
76
|
+
batch: false,
|
|
77
|
+
key: `${provider}-${i}`,
|
|
78
|
+
name: `${provider}-${i}`,
|
|
79
|
+
onFetchRequest: this.#config.onRequest ? (...args) => this.#config.onRequest?.(`${provider}-${i}`, ...args) : void 0,
|
|
80
|
+
onFetchResponse: this.#config.onResponse ? (...args) => this.#config.onResponse?.(`${provider}-${i}`, ...args) : void 0
|
|
81
|
+
}),
|
|
82
|
+
cooldown: cooldowns.get(url) ?? 0
|
|
83
|
+
})
|
|
84
|
+
);
|
|
85
|
+
if (this.#transports.length === 0) {
|
|
86
|
+
throw new NoAvailableTransportsError();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
get value() {
|
|
90
|
+
return {
|
|
91
|
+
rotate: (reason) => this.rotate(reason),
|
|
92
|
+
currentTransportName: this.currentTransportName
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
request = async (r) => {
|
|
96
|
+
if (this.#transports.length === 1) {
|
|
97
|
+
return this.#transport({ ...this.overrides }).request(r);
|
|
98
|
+
}
|
|
99
|
+
do {
|
|
100
|
+
try {
|
|
101
|
+
const resp = await this.#transport({ ...this.overrides }).request(r);
|
|
102
|
+
return resp;
|
|
103
|
+
} catch (e) {
|
|
104
|
+
if (e instanceof import_viem.RpcError || e instanceof import_viem.HttpRequestError) {
|
|
105
|
+
await this.rotate(e);
|
|
106
|
+
} else {
|
|
107
|
+
throw e;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
} while (this.#hasAvailableTransports);
|
|
111
|
+
throw new NoAvailableTransportsError();
|
|
112
|
+
};
|
|
113
|
+
get config() {
|
|
114
|
+
return {
|
|
115
|
+
key: "revolver",
|
|
116
|
+
name: "revolver",
|
|
117
|
+
type: "revolver",
|
|
118
|
+
request: this.request,
|
|
119
|
+
retryCount: this.#config.retryCount,
|
|
120
|
+
methods: void 0,
|
|
121
|
+
retryDelay: this.#config.retryDelay,
|
|
122
|
+
timeout: this.#config.timeout
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Manually rotate the transport
|
|
127
|
+
* @param reason
|
|
128
|
+
* @returns true if rotation was successful
|
|
129
|
+
*/
|
|
130
|
+
async rotate(reason) {
|
|
131
|
+
if (this.#transports.length === 1) {
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
this.#logger?.debug(
|
|
135
|
+
{
|
|
136
|
+
reason,
|
|
137
|
+
current: this.currentTransportName,
|
|
138
|
+
index: this.#index,
|
|
139
|
+
total: this.#transports.length
|
|
140
|
+
},
|
|
141
|
+
"rotating transport"
|
|
142
|
+
);
|
|
143
|
+
const oldTransportName = this.currentTransportName;
|
|
144
|
+
const now = Date.now();
|
|
145
|
+
this.#transports[this.#index].cooldown = now + (this.#config.cooldown ?? 6e4);
|
|
146
|
+
for (let i = 0; i < this.#transports.length - 1; i++) {
|
|
147
|
+
this.#index = (this.#index + 1) % this.#transports.length;
|
|
148
|
+
if (this.#transports[this.#index].cooldown < now) {
|
|
149
|
+
this.#logger?.info(
|
|
150
|
+
{
|
|
151
|
+
current: this.currentTransportName,
|
|
152
|
+
index: this.#index,
|
|
153
|
+
total: this.#transports.length
|
|
154
|
+
},
|
|
155
|
+
"switched to next transport"
|
|
156
|
+
);
|
|
157
|
+
await this.#config.onRotateSuccess?.(
|
|
158
|
+
oldTransportName,
|
|
159
|
+
this.currentTransportName,
|
|
160
|
+
reason
|
|
161
|
+
);
|
|
162
|
+
return true;
|
|
163
|
+
} else {
|
|
164
|
+
this.#logger?.warn(
|
|
165
|
+
{
|
|
166
|
+
current: this.currentTransportName,
|
|
167
|
+
index: this.#index,
|
|
168
|
+
total: this.#transports.length
|
|
169
|
+
},
|
|
170
|
+
"transport is still on cooldown"
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
await this.#config.onRotateFailed?.(reason);
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
get currentTransportName() {
|
|
178
|
+
return this.#transport({}).config.name;
|
|
179
|
+
}
|
|
180
|
+
get #logger() {
|
|
181
|
+
return this.#config.logger;
|
|
182
|
+
}
|
|
183
|
+
get #transport() {
|
|
184
|
+
return this.#transports[this.#index].transport;
|
|
185
|
+
}
|
|
186
|
+
get #hasAvailableTransports() {
|
|
187
|
+
const now = Date.now();
|
|
188
|
+
return this.#transports.some((t) => t.cooldown < now);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
192
|
+
0 && (module.exports = {
|
|
193
|
+
NoAvailableTransportsError,
|
|
194
|
+
RevolverTransport
|
|
195
|
+
});
|
package/dist/cjs/dev/index.js
CHANGED
|
@@ -21,11 +21,12 @@ __reExport(dev_exports, require("./calcLiquidatableLTs.js"), module.exports);
|
|
|
21
21
|
__reExport(dev_exports, require("./claimFromFaucet.js"), module.exports);
|
|
22
22
|
__reExport(dev_exports, require("./create2.js"), module.exports);
|
|
23
23
|
__reExport(dev_exports, require("./createAnvilClient.js"), module.exports);
|
|
24
|
-
__reExport(dev_exports, require("./createTransport.js"), module.exports);
|
|
25
24
|
__reExport(dev_exports, require("./detectChain.js"), module.exports);
|
|
26
25
|
__reExport(dev_exports, require("./EthCallSpy.js"), module.exports);
|
|
27
26
|
__reExport(dev_exports, require("./ltUtils.js"), module.exports);
|
|
28
27
|
__reExport(dev_exports, require("./migrateFaucet.js"), module.exports);
|
|
28
|
+
__reExport(dev_exports, require("./providers.js"), module.exports);
|
|
29
|
+
__reExport(dev_exports, require("./RevolverTransport.js"), module.exports);
|
|
29
30
|
__reExport(dev_exports, require("./types.js"), module.exports);
|
|
30
31
|
// Annotate the CommonJS export names for ESM import in node:
|
|
31
32
|
0 && (module.exports = {
|
|
@@ -35,10 +36,11 @@ __reExport(dev_exports, require("./types.js"), module.exports);
|
|
|
35
36
|
...require("./claimFromFaucet.js"),
|
|
36
37
|
...require("./create2.js"),
|
|
37
38
|
...require("./createAnvilClient.js"),
|
|
38
|
-
...require("./createTransport.js"),
|
|
39
39
|
...require("./detectChain.js"),
|
|
40
40
|
...require("./EthCallSpy.js"),
|
|
41
41
|
...require("./ltUtils.js"),
|
|
42
42
|
...require("./migrateFaucet.js"),
|
|
43
|
+
...require("./providers.js"),
|
|
44
|
+
...require("./RevolverTransport.js"),
|
|
43
45
|
...require("./types.js")
|
|
44
46
|
});
|
|
@@ -16,43 +16,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
16
16
|
return to;
|
|
17
17
|
};
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
var
|
|
20
|
-
__export(
|
|
21
|
-
createTransport: () => createTransport,
|
|
19
|
+
var providers_exports = {};
|
|
20
|
+
__export(providers_exports, {
|
|
22
21
|
getAlchemyUrl: () => getAlchemyUrl,
|
|
23
22
|
getDrpcUrl: () => getDrpcUrl,
|
|
24
23
|
getProviderUrl: () => getProviderUrl
|
|
25
24
|
});
|
|
26
|
-
module.exports = __toCommonJS(
|
|
27
|
-
var import_viem = require("viem");
|
|
25
|
+
module.exports = __toCommonJS(providers_exports);
|
|
28
26
|
var import_sdk = require("../sdk/index.js");
|
|
29
|
-
function createTransport(config) {
|
|
30
|
-
const { rpcProviders = [], protocol, network, ...rest } = config;
|
|
31
|
-
const rpcUrls = /* @__PURE__ */ new Map();
|
|
32
|
-
for (const { provider, keys } of rpcProviders) {
|
|
33
|
-
for (const key of keys) {
|
|
34
|
-
const url = getProviderUrl(provider, network, key, protocol);
|
|
35
|
-
if (url) {
|
|
36
|
-
rpcUrls.set(url, provider);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
const transports = Array.from(rpcUrls.entries()).map(
|
|
41
|
-
([url, provider], index) => protocol === "http" ? (0, import_viem.http)(url, {
|
|
42
|
-
...rest,
|
|
43
|
-
key: `${provider}-${index}`,
|
|
44
|
-
name: `${provider}-${index}`
|
|
45
|
-
}) : (0, import_viem.webSocket)(url, {
|
|
46
|
-
...rest,
|
|
47
|
-
key: `${provider}-${index}`,
|
|
48
|
-
name: `${provider}-${index}`
|
|
49
|
-
})
|
|
50
|
-
);
|
|
51
|
-
if (transports.length === 0) {
|
|
52
|
-
throw new Error("no fitting rpc urls found");
|
|
53
|
-
}
|
|
54
|
-
return transports.length > 1 ? (0, import_viem.fallback)(transports) : transports[0];
|
|
55
|
-
}
|
|
56
27
|
function getProviderUrl(provider, network, apiKey, protocol) {
|
|
57
28
|
switch (provider) {
|
|
58
29
|
case "alchemy":
|
|
@@ -97,7 +68,6 @@ function getDrpcUrl(network, apiKey, protocol) {
|
|
|
97
68
|
}
|
|
98
69
|
// Annotate the CommonJS export names for ESM import in node:
|
|
99
70
|
0 && (module.exports = {
|
|
100
|
-
createTransport,
|
|
101
71
|
getAlchemyUrl,
|
|
102
72
|
getDrpcUrl,
|
|
103
73
|
getProviderUrl
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BaseError,
|
|
3
|
+
HttpRequestError,
|
|
4
|
+
http,
|
|
5
|
+
RpcError
|
|
6
|
+
} from "viem";
|
|
7
|
+
import {
|
|
8
|
+
getProviderUrl
|
|
9
|
+
} from "./providers.js";
|
|
10
|
+
class NoAvailableTransportsError extends BaseError {
|
|
11
|
+
constructor() {
|
|
12
|
+
super("no available transports");
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
class RevolverTransport {
|
|
16
|
+
#transports;
|
|
17
|
+
#index = 0;
|
|
18
|
+
#config;
|
|
19
|
+
overrides;
|
|
20
|
+
/**
|
|
21
|
+
* Create a new RevolverTransport
|
|
22
|
+
* RevolverTransport usues several RPC providers and rotates between them when requests fail
|
|
23
|
+
* Failed transport goes into temporary cooldown, after which it can be tried again
|
|
24
|
+
* When all transports are on cooldown, the transport will throw a NoAvailableTransportsError
|
|
25
|
+
* @param config
|
|
26
|
+
* @returns
|
|
27
|
+
*/
|
|
28
|
+
static create(config) {
|
|
29
|
+
const transport = new RevolverTransport({
|
|
30
|
+
...config
|
|
31
|
+
});
|
|
32
|
+
return (...args) => {
|
|
33
|
+
transport.overrides = args[0];
|
|
34
|
+
return transport;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
constructor(config) {
|
|
38
|
+
this.#config = { ...config };
|
|
39
|
+
const rpcUrls = /* @__PURE__ */ new Map();
|
|
40
|
+
const cooldowns = /* @__PURE__ */ new Map();
|
|
41
|
+
for (const { provider, keys, cooldown } of config.providers) {
|
|
42
|
+
for (const key of keys) {
|
|
43
|
+
const url = getProviderUrl(provider, config.network, key, "http");
|
|
44
|
+
if (url) {
|
|
45
|
+
rpcUrls.set(url, provider);
|
|
46
|
+
if (cooldown) {
|
|
47
|
+
cooldowns.set(url, cooldown);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
this.#transports = Array.from(rpcUrls.entries()).map(
|
|
53
|
+
([url, provider], i) => ({
|
|
54
|
+
provider,
|
|
55
|
+
transport: http(url, {
|
|
56
|
+
retryCount: config.retryCount,
|
|
57
|
+
retryDelay: config.retryDelay,
|
|
58
|
+
timeout: config.timeout,
|
|
59
|
+
batch: false,
|
|
60
|
+
key: `${provider}-${i}`,
|
|
61
|
+
name: `${provider}-${i}`,
|
|
62
|
+
onFetchRequest: this.#config.onRequest ? (...args) => this.#config.onRequest?.(`${provider}-${i}`, ...args) : void 0,
|
|
63
|
+
onFetchResponse: this.#config.onResponse ? (...args) => this.#config.onResponse?.(`${provider}-${i}`, ...args) : void 0
|
|
64
|
+
}),
|
|
65
|
+
cooldown: cooldowns.get(url) ?? 0
|
|
66
|
+
})
|
|
67
|
+
);
|
|
68
|
+
if (this.#transports.length === 0) {
|
|
69
|
+
throw new NoAvailableTransportsError();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
get value() {
|
|
73
|
+
return {
|
|
74
|
+
rotate: (reason) => this.rotate(reason),
|
|
75
|
+
currentTransportName: this.currentTransportName
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
request = async (r) => {
|
|
79
|
+
if (this.#transports.length === 1) {
|
|
80
|
+
return this.#transport({ ...this.overrides }).request(r);
|
|
81
|
+
}
|
|
82
|
+
do {
|
|
83
|
+
try {
|
|
84
|
+
const resp = await this.#transport({ ...this.overrides }).request(r);
|
|
85
|
+
return resp;
|
|
86
|
+
} catch (e) {
|
|
87
|
+
if (e instanceof RpcError || e instanceof HttpRequestError) {
|
|
88
|
+
await this.rotate(e);
|
|
89
|
+
} else {
|
|
90
|
+
throw e;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
} while (this.#hasAvailableTransports);
|
|
94
|
+
throw new NoAvailableTransportsError();
|
|
95
|
+
};
|
|
96
|
+
get config() {
|
|
97
|
+
return {
|
|
98
|
+
key: "revolver",
|
|
99
|
+
name: "revolver",
|
|
100
|
+
type: "revolver",
|
|
101
|
+
request: this.request,
|
|
102
|
+
retryCount: this.#config.retryCount,
|
|
103
|
+
methods: void 0,
|
|
104
|
+
retryDelay: this.#config.retryDelay,
|
|
105
|
+
timeout: this.#config.timeout
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Manually rotate the transport
|
|
110
|
+
* @param reason
|
|
111
|
+
* @returns true if rotation was successful
|
|
112
|
+
*/
|
|
113
|
+
async rotate(reason) {
|
|
114
|
+
if (this.#transports.length === 1) {
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
this.#logger?.debug(
|
|
118
|
+
{
|
|
119
|
+
reason,
|
|
120
|
+
current: this.currentTransportName,
|
|
121
|
+
index: this.#index,
|
|
122
|
+
total: this.#transports.length
|
|
123
|
+
},
|
|
124
|
+
"rotating transport"
|
|
125
|
+
);
|
|
126
|
+
const oldTransportName = this.currentTransportName;
|
|
127
|
+
const now = Date.now();
|
|
128
|
+
this.#transports[this.#index].cooldown = now + (this.#config.cooldown ?? 6e4);
|
|
129
|
+
for (let i = 0; i < this.#transports.length - 1; i++) {
|
|
130
|
+
this.#index = (this.#index + 1) % this.#transports.length;
|
|
131
|
+
if (this.#transports[this.#index].cooldown < now) {
|
|
132
|
+
this.#logger?.info(
|
|
133
|
+
{
|
|
134
|
+
current: this.currentTransportName,
|
|
135
|
+
index: this.#index,
|
|
136
|
+
total: this.#transports.length
|
|
137
|
+
},
|
|
138
|
+
"switched to next transport"
|
|
139
|
+
);
|
|
140
|
+
await this.#config.onRotateSuccess?.(
|
|
141
|
+
oldTransportName,
|
|
142
|
+
this.currentTransportName,
|
|
143
|
+
reason
|
|
144
|
+
);
|
|
145
|
+
return true;
|
|
146
|
+
} else {
|
|
147
|
+
this.#logger?.warn(
|
|
148
|
+
{
|
|
149
|
+
current: this.currentTransportName,
|
|
150
|
+
index: this.#index,
|
|
151
|
+
total: this.#transports.length
|
|
152
|
+
},
|
|
153
|
+
"transport is still on cooldown"
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
await this.#config.onRotateFailed?.(reason);
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
get currentTransportName() {
|
|
161
|
+
return this.#transport({}).config.name;
|
|
162
|
+
}
|
|
163
|
+
get #logger() {
|
|
164
|
+
return this.#config.logger;
|
|
165
|
+
}
|
|
166
|
+
get #transport() {
|
|
167
|
+
return this.#transports[this.#index].transport;
|
|
168
|
+
}
|
|
169
|
+
get #hasAvailableTransports() {
|
|
170
|
+
const now = Date.now();
|
|
171
|
+
return this.#transports.some((t) => t.cooldown < now);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
export {
|
|
175
|
+
NoAvailableTransportsError,
|
|
176
|
+
RevolverTransport
|
|
177
|
+
};
|
package/dist/esm/dev/index.js
CHANGED
|
@@ -4,9 +4,10 @@ export * from "./calcLiquidatableLTs.js";
|
|
|
4
4
|
export * from "./claimFromFaucet.js";
|
|
5
5
|
export * from "./create2.js";
|
|
6
6
|
export * from "./createAnvilClient.js";
|
|
7
|
-
export * from "./createTransport.js";
|
|
8
7
|
export * from "./detectChain.js";
|
|
9
8
|
export * from "./EthCallSpy.js";
|
|
10
9
|
export * from "./ltUtils.js";
|
|
11
10
|
export * from "./migrateFaucet.js";
|
|
11
|
+
export * from "./providers.js";
|
|
12
|
+
export * from "./RevolverTransport.js";
|
|
12
13
|
export * from "./types.js";
|
|
@@ -1,32 +1,4 @@
|
|
|
1
|
-
import { fallback, http, webSocket } from "viem";
|
|
2
1
|
import { getChain } from "../sdk/index.js";
|
|
3
|
-
function createTransport(config) {
|
|
4
|
-
const { rpcProviders = [], protocol, network, ...rest } = config;
|
|
5
|
-
const rpcUrls = /* @__PURE__ */ new Map();
|
|
6
|
-
for (const { provider, keys } of rpcProviders) {
|
|
7
|
-
for (const key of keys) {
|
|
8
|
-
const url = getProviderUrl(provider, network, key, protocol);
|
|
9
|
-
if (url) {
|
|
10
|
-
rpcUrls.set(url, provider);
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
const transports = Array.from(rpcUrls.entries()).map(
|
|
15
|
-
([url, provider], index) => protocol === "http" ? http(url, {
|
|
16
|
-
...rest,
|
|
17
|
-
key: `${provider}-${index}`,
|
|
18
|
-
name: `${provider}-${index}`
|
|
19
|
-
}) : webSocket(url, {
|
|
20
|
-
...rest,
|
|
21
|
-
key: `${provider}-${index}`,
|
|
22
|
-
name: `${provider}-${index}`
|
|
23
|
-
})
|
|
24
|
-
);
|
|
25
|
-
if (transports.length === 0) {
|
|
26
|
-
throw new Error("no fitting rpc urls found");
|
|
27
|
-
}
|
|
28
|
-
return transports.length > 1 ? fallback(transports) : transports[0];
|
|
29
|
-
}
|
|
30
2
|
function getProviderUrl(provider, network, apiKey, protocol) {
|
|
31
3
|
switch (provider) {
|
|
32
4
|
case "alchemy":
|
|
@@ -70,7 +42,6 @@ function getDrpcUrl(network, apiKey, protocol) {
|
|
|
70
42
|
return net ? `${protocol}s://lb.drpc.org/${net}/${apiKey}` : void 0;
|
|
71
43
|
}
|
|
72
44
|
export {
|
|
73
|
-
createTransport,
|
|
74
45
|
getAlchemyUrl,
|
|
75
46
|
getDrpcUrl,
|
|
76
47
|
getProviderUrl
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { BaseError, type ClientConfig, type EIP1193RequestFn, type Transport, type TransportConfig } from "viem";
|
|
2
|
+
import type { HttpRpcClientOptions } from "viem/utils";
|
|
3
|
+
import type { ILogger, NetworkType } from "../sdk/index.js";
|
|
4
|
+
import { type ProviderConfig } from "./providers.js";
|
|
5
|
+
type OnRequestFn = (providerName: string, ...args: Parameters<Required<HttpRpcClientOptions>["onRequest"]>) => ReturnType<Required<HttpRpcClientOptions>["onRequest"]>;
|
|
6
|
+
type OnResponseFn = (providerName: string, ...args: Parameters<Required<HttpRpcClientOptions>["onResponse"]>) => ReturnType<Required<HttpRpcClientOptions>["onResponse"]>;
|
|
7
|
+
export interface RevolverTransportConfig {
|
|
8
|
+
network: NetworkType;
|
|
9
|
+
providers: ProviderConfig[];
|
|
10
|
+
logger?: ILogger;
|
|
11
|
+
key?: TransportConfig["key"] | undefined;
|
|
12
|
+
name?: TransportConfig["name"] | undefined;
|
|
13
|
+
pollingInterval?: ClientConfig["pollingInterval"] | undefined;
|
|
14
|
+
retryCount?: TransportConfig["retryCount"] | undefined;
|
|
15
|
+
retryDelay?: TransportConfig["retryDelay"] | undefined;
|
|
16
|
+
timeout?: TransportConfig["timeout"] | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Spying function that also returns provider name in additional to the request
|
|
19
|
+
*/
|
|
20
|
+
onRequest?: OnRequestFn;
|
|
21
|
+
/**
|
|
22
|
+
* Spying function that also returns provider name in additional to the response
|
|
23
|
+
*/
|
|
24
|
+
onResponse?: OnResponseFn;
|
|
25
|
+
/**
|
|
26
|
+
* Callback that is called when the transport is rotated
|
|
27
|
+
*/
|
|
28
|
+
onRotateSuccess?: (oldTransportName: string, newTransportName: string, reason?: BaseError) => void | Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* Callback that is called when the transport cannot be rotated
|
|
31
|
+
*/
|
|
32
|
+
onRotateFailed?: (reason?: BaseError) => void | Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* How long, in milliseconds, to wait before try this transport again
|
|
35
|
+
*/
|
|
36
|
+
cooldown?: number | undefined;
|
|
37
|
+
}
|
|
38
|
+
export declare class NoAvailableTransportsError extends BaseError {
|
|
39
|
+
constructor();
|
|
40
|
+
}
|
|
41
|
+
export interface RevolverTransportValue {
|
|
42
|
+
/**
|
|
43
|
+
* Manually rotate the transport
|
|
44
|
+
* @param reason
|
|
45
|
+
* @returns true if rotation was successful
|
|
46
|
+
*/
|
|
47
|
+
rotate: (reason?: BaseError) => Promise<boolean>;
|
|
48
|
+
/**
|
|
49
|
+
* The name of the current transport
|
|
50
|
+
*/
|
|
51
|
+
currentTransportName: string;
|
|
52
|
+
}
|
|
53
|
+
export declare class RevolverTransport implements ReturnType<Transport<"revolver", RevolverTransportValue>> {
|
|
54
|
+
#private;
|
|
55
|
+
private overrides?;
|
|
56
|
+
/**
|
|
57
|
+
* Create a new RevolverTransport
|
|
58
|
+
* RevolverTransport usues several RPC providers and rotates between them when requests fail
|
|
59
|
+
* Failed transport goes into temporary cooldown, after which it can be tried again
|
|
60
|
+
* When all transports are on cooldown, the transport will throw a NoAvailableTransportsError
|
|
61
|
+
* @param config
|
|
62
|
+
* @returns
|
|
63
|
+
*/
|
|
64
|
+
static create(config: RevolverTransportConfig): Transport<"revolver">;
|
|
65
|
+
constructor(config: RevolverTransportConfig);
|
|
66
|
+
get value(): RevolverTransportValue;
|
|
67
|
+
request: EIP1193RequestFn;
|
|
68
|
+
get config(): TransportConfig<"revolver">;
|
|
69
|
+
/**
|
|
70
|
+
* Manually rotate the transport
|
|
71
|
+
* @param reason
|
|
72
|
+
* @returns true if rotation was successful
|
|
73
|
+
*/
|
|
74
|
+
rotate(reason?: BaseError): Promise<boolean>;
|
|
75
|
+
get currentTransportName(): string;
|
|
76
|
+
}
|
|
77
|
+
export {};
|
|
@@ -4,9 +4,10 @@ export * from "./calcLiquidatableLTs.js";
|
|
|
4
4
|
export * from "./claimFromFaucet.js";
|
|
5
5
|
export * from "./create2.js";
|
|
6
6
|
export * from "./createAnvilClient.js";
|
|
7
|
-
export * from "./createTransport.js";
|
|
8
7
|
export * from "./detectChain.js";
|
|
9
8
|
export * from "./EthCallSpy.js";
|
|
10
9
|
export * from "./ltUtils.js";
|
|
11
10
|
export * from "./migrateFaucet.js";
|
|
11
|
+
export * from "./providers.js";
|
|
12
|
+
export * from "./RevolverTransport.js";
|
|
12
13
|
export * from "./types.js";
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import type { HttpTransportConfig,
|
|
1
|
+
import type { HttpTransportConfig, WebSocketTransportConfig } from "viem";
|
|
2
2
|
import type { NetworkType } from "../sdk/index.js";
|
|
3
3
|
export type RpcProvider = "alchemy" | "drpc" | "custom";
|
|
4
4
|
export interface ProviderConfig {
|
|
5
5
|
provider: RpcProvider;
|
|
6
6
|
keys: string[];
|
|
7
|
+
cooldown?: number;
|
|
7
8
|
}
|
|
8
9
|
export interface CreateTransportURLOptions {
|
|
9
10
|
/**
|
|
@@ -19,13 +20,6 @@ export type CreateWSTransportConfig = {
|
|
|
19
20
|
protocol: "ws";
|
|
20
21
|
} & WebSocketTransportConfig & CreateTransportURLOptions;
|
|
21
22
|
export type CreateTransportConfig = CreateHTTPTransportConfig | CreateWSTransportConfig;
|
|
22
|
-
/**
|
|
23
|
-
* Helper method to create viem Transport using API keys of well-known RPC providers and explicit fallback URLs
|
|
24
|
-
* Currently only supports Alchemy
|
|
25
|
-
* @param config
|
|
26
|
-
* @returns
|
|
27
|
-
*/
|
|
28
|
-
export declare function createTransport(config: CreateTransportConfig): Transport;
|
|
29
23
|
export declare function getProviderUrl(provider: RpcProvider, network: NetworkType, apiKey: string, protocol: "http" | "ws"): string | undefined;
|
|
30
24
|
export declare function getAlchemyUrl(network: NetworkType, apiKey: string, protocol: "http" | "ws"): string | undefined;
|
|
31
25
|
export declare function getDrpcUrl(network: NetworkType, apiKey: string, protocol: "http" | "ws"): string | undefined;
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|