feat(express-relay): Support websocket in the js sdk (#1301)
This commit is contained in:
parent
3c1348c530
commit
f22c0c8ae6
|
@ -35,24 +35,22 @@ import {
|
|||
|
||||
const client = new Client({ baseUrl: "https://per-staging.dourolabs.app/" });
|
||||
|
||||
function calculateOpportunityBid(
|
||||
opportunity: OpportunityParams
|
||||
): BidInfo | null {
|
||||
function calculateOpportunityBid(opportunity: Opportunity): BidInfo | null {
|
||||
// searcher implementation here
|
||||
// if the opportunity is not suitable for the searcher, return null
|
||||
}
|
||||
const opportunities = await client.getOpportunities();
|
||||
|
||||
for (const opportunity of opportunities) {
|
||||
const bidInfo = calculateOpportunityBid(order);
|
||||
if (bidInfo === null) continue;
|
||||
client.setOpportunityHandler(async (opportunity: Opportunity) => {
|
||||
const bidInfo = calculateOpportunityBid(opportunity);
|
||||
if (bidInfo === null) return;
|
||||
const opportunityBid = await client.signOpportunityBid(
|
||||
opportunity,
|
||||
bidInfo,
|
||||
privateKey // searcher private key with appropriate permissions and assets
|
||||
);
|
||||
await client.submitOpportunityBid(opportunityBid);
|
||||
}
|
||||
});
|
||||
await client.subscribeChains([chain_id]); // chain id you want to subscribe to
|
||||
```
|
||||
|
||||
### Example
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@pythnetwork/express-relay-evm-js",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.1",
|
||||
"description": "Utilities for interacting with the express relay protocol",
|
||||
"homepage": "https://pyth.network",
|
||||
"author": {
|
||||
|
@ -36,20 +36,22 @@
|
|||
"directory": "express_relay/sdk/js"
|
||||
},
|
||||
"dependencies": {
|
||||
"isomorphic-ws": "^5.0.0",
|
||||
"openapi-client-axios": "^7.5.4",
|
||||
"openapi-fetch": "^0.8.2",
|
||||
"viem": "^2.7.6"
|
||||
"viem": "^2.7.6",
|
||||
"ws": "^8.16.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/yargs": "^17.0.10",
|
||||
"@typescript-eslint/eslint-plugin": "^5.21.0",
|
||||
"@typescript-eslint/parser": "^5.21.0",
|
||||
"eslint": "^8.56.0",
|
||||
"jest": "^27.5.1",
|
||||
"openapi-typescript": "^6.5.5",
|
||||
"prettier": "^2.6.2",
|
||||
"typescript": "^5.1",
|
||||
"yargs": "^17.4.1",
|
||||
"jest": "^27.5.1"
|
||||
"yargs": "^17.4.1"
|
||||
},
|
||||
"license": "Apache-2.0"
|
||||
}
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
import yargs from "yargs";
|
||||
import { hideBin } from "yargs/helpers";
|
||||
import { Client } from "../index";
|
||||
import { checkHex, Client } from "../index";
|
||||
import { privateKeyToAccount } from "viem/accounts";
|
||||
import { isHex } from "viem";
|
||||
|
||||
function sleep(ms: number) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
const argv = yargs(hideBin(process.argv))
|
||||
.option("endpoint", {
|
||||
description:
|
||||
|
@ -18,6 +14,7 @@ const argv = yargs(hideBin(process.argv))
|
|||
.option("chain-id", {
|
||||
description: "Chain id to fetch opportunities for. e.g: sepolia",
|
||||
type: "string",
|
||||
demandOption: true,
|
||||
})
|
||||
.option("bid", {
|
||||
description: "Bid amount in wei",
|
||||
|
@ -43,35 +40,38 @@ async function run() {
|
|||
throw new Error(`Invalid private key: ${argv.privateKey}`);
|
||||
}
|
||||
const DAY_IN_SECONDS = 60 * 60 * 24;
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (true) {
|
||||
const opportunities = await client.getOpportunities(argv.chainId);
|
||||
console.log(`Fetched ${opportunities.length} opportunities`);
|
||||
for (const opportunity of opportunities) {
|
||||
const bid = BigInt(argv.bid);
|
||||
// Bid info should be generated by evaluating the opportunity
|
||||
// here for simplicity we are using a constant bid and 24 hours of validity
|
||||
const bidInfo = {
|
||||
amount: bid,
|
||||
validUntil: BigInt(Math.round(Date.now() / 1000 + DAY_IN_SECONDS)),
|
||||
};
|
||||
const opportunityBid = await client.signOpportunityBid(
|
||||
opportunity,
|
||||
bidInfo,
|
||||
argv.privateKey
|
||||
client.setOpportunityHandler(async (opportunity) => {
|
||||
const bid = BigInt(argv.bid);
|
||||
// Bid info should be generated by evaluating the opportunity
|
||||
// here for simplicity we are using a constant bid and 24 hours of validity
|
||||
const bidInfo = {
|
||||
amount: bid,
|
||||
validUntil: BigInt(Math.round(Date.now() / 1000 + DAY_IN_SECONDS)),
|
||||
};
|
||||
const opportunityBid = await client.signOpportunityBid(
|
||||
opportunity,
|
||||
bidInfo,
|
||||
checkHex(argv.privateKey)
|
||||
);
|
||||
try {
|
||||
await client.submitOpportunityBid(opportunityBid);
|
||||
console.log(
|
||||
`Successful bid ${bid} on opportunity ${opportunity.opportunityId}`
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`Failed to bid on opportunity ${opportunity.opportunityId}: ${error}`
|
||||
);
|
||||
try {
|
||||
await client.submitOpportunityBid(opportunityBid);
|
||||
console.log(
|
||||
`Successful bid ${bid} on opportunity ${opportunity.opportunityId}`
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`Failed to bid on opportunity ${opportunity.opportunityId}: ${error}`
|
||||
);
|
||||
}
|
||||
}
|
||||
await sleep(5000);
|
||||
});
|
||||
try {
|
||||
await client.subscribeChains([argv.chainId]);
|
||||
console.log(
|
||||
`Subscribed to chain ${argv.chainId}. Waiting for opportunities...`
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
client.websocket?.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import type { paths } from "./types";
|
||||
import createClient, { ClientOptions } from "openapi-fetch";
|
||||
import type { paths, components } from "./types";
|
||||
import createClient, {
|
||||
ClientOptions as FetchClientOptions,
|
||||
} from "openapi-fetch";
|
||||
import {
|
||||
Address,
|
||||
encodeAbiParameters,
|
||||
|
@ -10,7 +12,7 @@ import {
|
|||
keccak256,
|
||||
} from "viem";
|
||||
import { privateKeyToAccount, sign, signatureToHex } from "viem/accounts";
|
||||
|
||||
import WebSocket from "isomorphic-ws";
|
||||
/**
|
||||
* ERC20 token with contract address and amount
|
||||
*/
|
||||
|
@ -118,11 +120,172 @@ function checkTokenQty(token: { contract: string; amount: string }): TokenQty {
|
|||
};
|
||||
}
|
||||
|
||||
export class Client {
|
||||
private clientOptions?: ClientOptions;
|
||||
type ClientOptions = FetchClientOptions & { baseUrl: string };
|
||||
|
||||
constructor(clientOptions?: ClientOptions) {
|
||||
export interface WsOptions {
|
||||
/**
|
||||
* Max time to wait for a response from the server in milliseconds
|
||||
*/
|
||||
response_timeout: number;
|
||||
}
|
||||
|
||||
const DEFAULT_WS_OPTIONS: WsOptions = {
|
||||
response_timeout: 5000,
|
||||
};
|
||||
|
||||
export class Client {
|
||||
public clientOptions: ClientOptions;
|
||||
public wsOptions: WsOptions;
|
||||
public websocket?: WebSocket;
|
||||
public idCounter = 0;
|
||||
public callbackRouter: Record<
|
||||
string,
|
||||
(response: components["schemas"]["ServerResultMessage"]) => void
|
||||
> = {};
|
||||
private websocketOpportunityCallback?: (
|
||||
opportunity: Opportunity
|
||||
) => Promise<void>;
|
||||
|
||||
constructor(clientOptions: ClientOptions, wsOptions?: WsOptions) {
|
||||
this.clientOptions = clientOptions;
|
||||
this.wsOptions = { ...DEFAULT_WS_OPTIONS, ...wsOptions };
|
||||
}
|
||||
|
||||
private connectWebsocket() {
|
||||
const websocketEndpoint = new URL(this.clientOptions.baseUrl);
|
||||
websocketEndpoint.protocol =
|
||||
websocketEndpoint.protocol === "https:" ? "wss:" : "ws:";
|
||||
websocketEndpoint.pathname = "/v1/ws";
|
||||
|
||||
this.websocket = new WebSocket(websocketEndpoint.toString());
|
||||
this.websocket.on("message", async (data) => {
|
||||
const message:
|
||||
| components["schemas"]["ServerResultResponse"]
|
||||
| components["schemas"]["ServerUpdateResponse"] = JSON.parse(
|
||||
data.toString()
|
||||
);
|
||||
if ("id" in message && message.id) {
|
||||
const callback = this.callbackRouter[message.id];
|
||||
if (callback !== undefined) {
|
||||
callback(message);
|
||||
delete this.callbackRouter[message.id];
|
||||
}
|
||||
} else if ("type" in message && message.type === "new_opportunity") {
|
||||
if (this.websocketOpportunityCallback !== undefined) {
|
||||
const convertedOpportunity = this.convertOpportunity(
|
||||
message.opportunity
|
||||
);
|
||||
if (convertedOpportunity !== undefined) {
|
||||
await this.websocketOpportunityCallback(convertedOpportunity);
|
||||
}
|
||||
}
|
||||
} else if ("error" in message) {
|
||||
// Can not route error messages to the callback router as they don't have an id
|
||||
console.error(message.error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an opportunity from the server to the client format
|
||||
* Returns undefined if the opportunity version is not supported
|
||||
* @param opportunity
|
||||
*/
|
||||
private convertOpportunity(
|
||||
opportunity: components["schemas"]["OpportunityParamsWithMetadata"]
|
||||
): Opportunity | undefined {
|
||||
if (opportunity.version != "v1") {
|
||||
console.warn(
|
||||
`Can not handle opportunity version: ${opportunity.version}. Please upgrade your client.`
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
chainId: opportunity.chain_id,
|
||||
opportunityId: opportunity.opportunity_id,
|
||||
permissionKey: checkHex(opportunity.permission_key),
|
||||
contract: checkAddress(opportunity.contract),
|
||||
calldata: checkHex(opportunity.calldata),
|
||||
value: BigInt(opportunity.value),
|
||||
repayTokens: opportunity.repay_tokens.map(checkTokenQty),
|
||||
receiptTokens: opportunity.receipt_tokens.map(checkTokenQty),
|
||||
};
|
||||
}
|
||||
|
||||
public setOpportunityHandler(
|
||||
callback: (opportunity: Opportunity) => Promise<void>
|
||||
) {
|
||||
this.websocketOpportunityCallback = callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribes to the specified chains
|
||||
*
|
||||
* The opportunity handler will be called for opportunities on the specified chains
|
||||
* If the opportunity handler is not set, an error will be thrown
|
||||
* @param chains
|
||||
*/
|
||||
async subscribeChains(chains: string[]) {
|
||||
if (this.websocketOpportunityCallback === undefined) {
|
||||
throw new Error("Opportunity handler not set");
|
||||
}
|
||||
return this.sendWebsocketMessage({
|
||||
method: "subscribe",
|
||||
params: {
|
||||
chain_ids: chains,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsubscribes from the specified chains
|
||||
*
|
||||
* The opportunity handler will no longer be called for opportunities on the specified chains
|
||||
* @param chains
|
||||
*/
|
||||
async unsubscribeChains(chains: string[]) {
|
||||
return this.sendWebsocketMessage({
|
||||
method: "unsubscribe",
|
||||
params: {
|
||||
chain_ids: chains,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async sendWebsocketMessage(
|
||||
msg: components["schemas"]["ClientMessage"]
|
||||
): Promise<void> {
|
||||
const msg_with_id: components["schemas"]["ClientRequest"] = {
|
||||
...msg,
|
||||
id: (this.idCounter++).toString(),
|
||||
};
|
||||
return new Promise((resolve, reject) => {
|
||||
this.callbackRouter[msg_with_id.id] = (response) => {
|
||||
if (response.status === "success") {
|
||||
resolve();
|
||||
} else {
|
||||
reject(response.result);
|
||||
}
|
||||
};
|
||||
if (this.websocket === undefined) {
|
||||
this.connectWebsocket();
|
||||
}
|
||||
if (this.websocket !== undefined) {
|
||||
if (this.websocket.readyState === WebSocket.CONNECTING) {
|
||||
this.websocket.on("open", () => {
|
||||
this.websocket?.send(JSON.stringify(msg_with_id));
|
||||
});
|
||||
} else if (this.websocket.readyState === WebSocket.OPEN) {
|
||||
this.websocket.send(JSON.stringify(msg_with_id));
|
||||
} else {
|
||||
reject("Websocket connection closing or already closed");
|
||||
}
|
||||
}
|
||||
setTimeout(() => {
|
||||
delete this.callbackRouter[msg_with_id.id];
|
||||
reject("Websocket response timeout");
|
||||
}, this.wsOptions.response_timeout);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -138,22 +301,11 @@ export class Client {
|
|||
throw new Error("No opportunities found");
|
||||
}
|
||||
return opportunities.data.flatMap((opportunity) => {
|
||||
if (opportunity.version != "v1") {
|
||||
console.warn(
|
||||
`Can not handle opportunity version: ${opportunity.version}. Please upgrade your client.`
|
||||
);
|
||||
const convertedOpportunity = this.convertOpportunity(opportunity);
|
||||
if (convertedOpportunity === undefined) {
|
||||
return [];
|
||||
}
|
||||
return {
|
||||
chainId: opportunity.chain_id,
|
||||
opportunityId: opportunity.opportunity_id,
|
||||
permissionKey: checkHex(opportunity.permission_key),
|
||||
contract: checkAddress(opportunity.contract),
|
||||
calldata: checkHex(opportunity.calldata),
|
||||
value: BigInt(opportunity.value),
|
||||
repayTokens: opportunity.repay_tokens.map(checkTokenQty),
|
||||
receiptTokens: opportunity.receipt_tokens.map(checkTokenQty),
|
||||
};
|
||||
return convertedOpportunity;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -72,6 +72,24 @@ export interface components {
|
|||
BidResult: {
|
||||
status: string;
|
||||
};
|
||||
ClientMessage:
|
||||
| {
|
||||
/** @enum {string} */
|
||||
method: "subscribe";
|
||||
params: {
|
||||
chain_ids: components["schemas"]["ChainId"][];
|
||||
};
|
||||
}
|
||||
| {
|
||||
/** @enum {string} */
|
||||
method: "unsubscribe";
|
||||
params: {
|
||||
chain_ids: components["schemas"]["ChainId"][];
|
||||
};
|
||||
};
|
||||
ClientRequest: components["schemas"]["ClientMessage"] & {
|
||||
id: string;
|
||||
};
|
||||
ErrorBodyResponse: {
|
||||
error: string;
|
||||
};
|
||||
|
@ -139,13 +157,37 @@ export interface components {
|
|||
value: string;
|
||||
};
|
||||
/** @description Similar to OpportunityParams, but with the opportunity id included. */
|
||||
OpportunityParamsWithId: components["schemas"]["OpportunityParams"] & {
|
||||
OpportunityParamsWithMetadata: components["schemas"]["OpportunityParams"] & {
|
||||
creation_time: components["schemas"]["UnixTimestamp"];
|
||||
/**
|
||||
* @description The opportunity unique id
|
||||
* @example f47ac10b-58cc-4372-a567-0e02b2c3d479
|
||||
*/
|
||||
opportunity_id: string;
|
||||
};
|
||||
ServerResultMessage:
|
||||
| {
|
||||
/** @enum {string} */
|
||||
status: "success";
|
||||
}
|
||||
| {
|
||||
result: string;
|
||||
/** @enum {string} */
|
||||
status: "error";
|
||||
};
|
||||
/**
|
||||
* @description This enum is used to send the result for a specific client request with the same id
|
||||
* id is only None when the client message is invalid
|
||||
*/
|
||||
ServerResultResponse: components["schemas"]["ServerResultMessage"] & {
|
||||
id?: string | null;
|
||||
};
|
||||
/** @description This enum is used to send an update to the client for any subscriptions made */
|
||||
ServerUpdateResponse: {
|
||||
opportunity: components["schemas"]["OpportunityParamsWithMetadata"];
|
||||
/** @enum {string} */
|
||||
type: "new_opportunity";
|
||||
};
|
||||
TokenQty: {
|
||||
/**
|
||||
* @description Token amount
|
||||
|
@ -176,9 +218,10 @@ export interface components {
|
|||
};
|
||||
};
|
||||
/** @description Similar to OpportunityParams, but with the opportunity id included. */
|
||||
OpportunityParamsWithId: {
|
||||
OpportunityParamsWithMetadata: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["OpportunityParams"] & {
|
||||
creation_time: components["schemas"]["UnixTimestamp"];
|
||||
/**
|
||||
* @description The opportunity unique id
|
||||
* @example f47ac10b-58cc-4372-a567-0e02b2c3d479
|
||||
|
|
|
@ -612,12 +612,14 @@
|
|||
},
|
||||
"express_relay/sdk/js": {
|
||||
"name": "@pythnetwork/express-relay-evm-js",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.1",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"isomorphic-ws": "^5.0.0",
|
||||
"openapi-client-axios": "^7.5.4",
|
||||
"openapi-fetch": "^0.8.2",
|
||||
"viem": "^2.7.6"
|
||||
"viem": "^2.7.6",
|
||||
"ws": "^8.16.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/yargs": "^17.0.10",
|
||||
|
@ -1265,6 +1267,14 @@
|
|||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"express_relay/sdk/js/node_modules/isomorphic-ws": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz",
|
||||
"integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==",
|
||||
"peerDependencies": {
|
||||
"ws": "*"
|
||||
}
|
||||
},
|
||||
"express_relay/sdk/js/node_modules/jest": {
|
||||
"version": "27.5.1",
|
||||
"resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz",
|
||||
|
@ -1828,6 +1838,35 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"express_relay/sdk/js/node_modules/openapi-typescript": {
|
||||
"version": "6.5.5",
|
||||
"resolved": "https://registry.npmjs.org/openapi-typescript/-/openapi-typescript-6.5.5.tgz",
|
||||
"integrity": "sha512-pMsA8GrMQKtNOPPjKnJbDotA2UpKsIcTHecMw2Bl3M/2eWTVs8zAYBm/cgaE9Qz5GrcVCDIru9GQX/P9vxtUFg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ansi-colors": "^4.1.3",
|
||||
"fast-glob": "^3.3.1",
|
||||
"js-yaml": "^4.1.0",
|
||||
"supports-color": "^9.4.0",
|
||||
"undici": "^5.23.0",
|
||||
"yargs-parser": "^21.1.1"
|
||||
},
|
||||
"bin": {
|
||||
"openapi-typescript": "bin/cli.js"
|
||||
}
|
||||
},
|
||||
"express_relay/sdk/js/node_modules/openapi-typescript/node_modules/supports-color": {
|
||||
"version": "9.4.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz",
|
||||
"integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/supports-color?sponsor=1"
|
||||
}
|
||||
},
|
||||
"express_relay/sdk/js/node_modules/p-limit": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
|
||||
|
@ -1973,6 +2012,26 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"express_relay/sdk/js/node_modules/viem/node_modules/ws": {
|
||||
"version": "8.13.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
|
||||
"integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": ">=5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"express_relay/sdk/js/node_modules/write-file-atomic": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
|
||||
|
@ -1985,6 +2044,26 @@
|
|||
"typedarray-to-buffer": "^3.1.5"
|
||||
}
|
||||
},
|
||||
"express_relay/sdk/js/node_modules/ws": {
|
||||
"version": "8.16.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz",
|
||||
"integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": ">=5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"express_relay/sdk/js/node_modules/yargs": {
|
||||
"version": "17.7.2",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
|
||||
|
@ -27568,21 +27647,21 @@
|
|||
}
|
||||
},
|
||||
"node_modules/engine.io-client": {
|
||||
"version": "6.2.3",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.2.3.tgz",
|
||||
"integrity": "sha512-aXPtgF1JS3RuuKcpSrBtimSjYvrbhKW9froICH4s0F3XQWLxsKNxqzG39nnvQZQnva4CMvUK63T7shevxRyYHw==",
|
||||
"version": "6.5.3",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.3.tgz",
|
||||
"integrity": "sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==",
|
||||
"dependencies": {
|
||||
"@socket.io/component-emitter": "~3.1.0",
|
||||
"debug": "~4.3.1",
|
||||
"engine.io-parser": "~5.0.3",
|
||||
"ws": "~8.2.3",
|
||||
"engine.io-parser": "~5.2.1",
|
||||
"ws": "~8.11.0",
|
||||
"xmlhttprequest-ssl": "~2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/engine.io-client/node_modules/ws": {
|
||||
"version": "8.2.3",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz",
|
||||
"integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==",
|
||||
"version": "8.11.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
|
||||
"integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
|
@ -27600,9 +27679,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/engine.io-parser": {
|
||||
"version": "5.0.6",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.6.tgz",
|
||||
"integrity": "sha512-tjuoZDMAdEhVnSFleYPCtdL2GXwVTGtNjoeJd9IhIG3C1xs9uwxqRNEu5WpnDZCaozwVlK/nuQhpodhXSIMaxw==",
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz",
|
||||
"integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
|
@ -41349,49 +41428,11 @@
|
|||
"resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz",
|
||||
"integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="
|
||||
},
|
||||
"node_modules/openapi-typescript": {
|
||||
"version": "6.7.4",
|
||||
"resolved": "https://registry.npmjs.org/openapi-typescript/-/openapi-typescript-6.7.4.tgz",
|
||||
"integrity": "sha512-EZyeW9Wy7UDCKv0iYmKrq2pVZtquXiD/YHiUClAKqiMi42nodx/EQH11K6fLqjt1IZlJmVokrAsExsBMM2RROQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ansi-colors": "^4.1.3",
|
||||
"fast-glob": "^3.3.2",
|
||||
"js-yaml": "^4.1.0",
|
||||
"supports-color": "^9.4.0",
|
||||
"undici": "^5.28.2",
|
||||
"yargs-parser": "^21.1.1"
|
||||
},
|
||||
"bin": {
|
||||
"openapi-typescript": "bin/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/openapi-typescript-helpers": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/openapi-typescript-helpers/-/openapi-typescript-helpers-0.0.5.tgz",
|
||||
"integrity": "sha512-MRffg93t0hgGZbYTxg60hkRIK2sRuEOHEtCUgMuLgbCC33TMQ68AmxskzUlauzZYD47+ENeGV/ElI7qnWqrAxA=="
|
||||
},
|
||||
"node_modules/openapi-typescript/node_modules/supports-color": {
|
||||
"version": "9.4.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz",
|
||||
"integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/supports-color?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/openapi-typescript/node_modules/yargs-parser": {
|
||||
"version": "21.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
|
||||
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/optimism": {
|
||||
"version": "0.16.2",
|
||||
"resolved": "https://registry.npmjs.org/optimism/-/optimism-0.16.2.tgz",
|
||||
|
@ -49325,23 +49366,23 @@
|
|||
}
|
||||
},
|
||||
"node_modules/socket.io-client": {
|
||||
"version": "4.5.4",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.5.4.tgz",
|
||||
"integrity": "sha512-ZpKteoA06RzkD32IbqILZ+Cnst4xewU7ZYK12aS1mzHftFFjpoMz69IuhP/nL25pJfao/amoPI527KnuhFm01g==",
|
||||
"version": "4.7.4",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.4.tgz",
|
||||
"integrity": "sha512-wh+OkeF0rAVCrABWQBaEjLfb7DVPotMbu0cgWgyR0v6eA4EoVnAwcIeIbcdTE3GT/H3kbdLl7OoH2+asoDRIIg==",
|
||||
"dependencies": {
|
||||
"@socket.io/component-emitter": "~3.1.0",
|
||||
"debug": "~4.3.2",
|
||||
"engine.io-client": "~6.2.3",
|
||||
"socket.io-parser": "~4.2.1"
|
||||
"engine.io-client": "~6.5.2",
|
||||
"socket.io-parser": "~4.2.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/socket.io-parser": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.2.tgz",
|
||||
"integrity": "sha512-DJtziuKypFkMMHCm2uIshOYC7QaylbtzQwiMYDuCKy3OPkjLzu4B2vAhTlqipRHHzrI0NJeBAizTK7X+6m1jVw==",
|
||||
"version": "4.2.4",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz",
|
||||
"integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==",
|
||||
"dependencies": {
|
||||
"@socket.io/component-emitter": "~3.1.0",
|
||||
"debug": "~4.3.1"
|
||||
|
@ -67662,6 +67703,7 @@
|
|||
"@typescript-eslint/eslint-plugin": "^5.21.0",
|
||||
"@typescript-eslint/parser": "^5.21.0",
|
||||
"eslint": "^8.56.0",
|
||||
"isomorphic-ws": "^5.0.0",
|
||||
"jest": "^27.5.1",
|
||||
"openapi-client-axios": "^7.5.4",
|
||||
"openapi-fetch": "^0.8.2",
|
||||
|
@ -67669,6 +67711,7 @@
|
|||
"prettier": "^2.6.2",
|
||||
"typescript": "^5.1",
|
||||
"viem": "^2.7.6",
|
||||
"ws": "^8.16.0",
|
||||
"yargs": "^17.4.1"
|
||||
},
|
||||
"dependencies": {
|
||||
|
@ -68140,6 +68183,12 @@
|
|||
"is-glob": "^4.0.3"
|
||||
}
|
||||
},
|
||||
"isomorphic-ws": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz",
|
||||
"integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==",
|
||||
"requires": {}
|
||||
},
|
||||
"jest": {
|
||||
"version": "27.5.1",
|
||||
"resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz",
|
||||
|
@ -68586,6 +68635,28 @@
|
|||
"p-locate": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"openapi-typescript": {
|
||||
"version": "6.5.5",
|
||||
"resolved": "https://registry.npmjs.org/openapi-typescript/-/openapi-typescript-6.5.5.tgz",
|
||||
"integrity": "sha512-pMsA8GrMQKtNOPPjKnJbDotA2UpKsIcTHecMw2Bl3M/2eWTVs8zAYBm/cgaE9Qz5GrcVCDIru9GQX/P9vxtUFg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-colors": "^4.1.3",
|
||||
"fast-glob": "^3.3.1",
|
||||
"js-yaml": "^4.1.0",
|
||||
"supports-color": "^9.4.0",
|
||||
"undici": "^5.23.0",
|
||||
"yargs-parser": "^21.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"supports-color": {
|
||||
"version": "9.4.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz",
|
||||
"integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"p-limit": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
|
||||
|
@ -68680,6 +68751,14 @@
|
|||
"abitype": "1.0.0",
|
||||
"isows": "1.0.3",
|
||||
"ws": "8.13.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ws": {
|
||||
"version": "8.13.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
|
||||
"integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==",
|
||||
"requires": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"write-file-atomic": {
|
||||
|
@ -68694,6 +68773,12 @@
|
|||
"typedarray-to-buffer": "^3.1.5"
|
||||
}
|
||||
},
|
||||
"ws": {
|
||||
"version": "8.16.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz",
|
||||
"integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==",
|
||||
"requires": {}
|
||||
},
|
||||
"yargs": {
|
||||
"version": "17.7.2",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
|
||||
|
@ -83612,29 +83697,29 @@
|
|||
}
|
||||
},
|
||||
"engine.io-client": {
|
||||
"version": "6.2.3",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.2.3.tgz",
|
||||
"integrity": "sha512-aXPtgF1JS3RuuKcpSrBtimSjYvrbhKW9froICH4s0F3XQWLxsKNxqzG39nnvQZQnva4CMvUK63T7shevxRyYHw==",
|
||||
"version": "6.5.3",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.3.tgz",
|
||||
"integrity": "sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==",
|
||||
"requires": {
|
||||
"@socket.io/component-emitter": "~3.1.0",
|
||||
"debug": "~4.3.1",
|
||||
"engine.io-parser": "~5.0.3",
|
||||
"ws": "~8.2.3",
|
||||
"engine.io-parser": "~5.2.1",
|
||||
"ws": "~8.11.0",
|
||||
"xmlhttprequest-ssl": "~2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ws": {
|
||||
"version": "8.2.3",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz",
|
||||
"integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==",
|
||||
"version": "8.11.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
|
||||
"integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==",
|
||||
"requires": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"engine.io-parser": {
|
||||
"version": "5.0.6",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.6.tgz",
|
||||
"integrity": "sha512-tjuoZDMAdEhVnSFleYPCtdL2GXwVTGtNjoeJd9IhIG3C1xs9uwxqRNEu5WpnDZCaozwVlK/nuQhpodhXSIMaxw=="
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz",
|
||||
"integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw=="
|
||||
},
|
||||
"enhanced-resolve": {
|
||||
"version": "5.14.0",
|
||||
|
@ -94531,34 +94616,6 @@
|
|||
"resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz",
|
||||
"integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="
|
||||
},
|
||||
"openapi-typescript": {
|
||||
"version": "6.7.4",
|
||||
"resolved": "https://registry.npmjs.org/openapi-typescript/-/openapi-typescript-6.7.4.tgz",
|
||||
"integrity": "sha512-EZyeW9Wy7UDCKv0iYmKrq2pVZtquXiD/YHiUClAKqiMi42nodx/EQH11K6fLqjt1IZlJmVokrAsExsBMM2RROQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-colors": "^4.1.3",
|
||||
"fast-glob": "^3.3.2",
|
||||
"js-yaml": "^4.1.0",
|
||||
"supports-color": "^9.4.0",
|
||||
"undici": "^5.28.2",
|
||||
"yargs-parser": "^21.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"supports-color": {
|
||||
"version": "9.4.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz",
|
||||
"integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==",
|
||||
"dev": true
|
||||
},
|
||||
"yargs-parser": {
|
||||
"version": "21.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
|
||||
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"openapi-typescript-helpers": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/openapi-typescript-helpers/-/openapi-typescript-helpers-0.0.5.tgz",
|
||||
|
@ -100948,20 +101005,20 @@
|
|||
}
|
||||
},
|
||||
"socket.io-client": {
|
||||
"version": "4.5.4",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.5.4.tgz",
|
||||
"integrity": "sha512-ZpKteoA06RzkD32IbqILZ+Cnst4xewU7ZYK12aS1mzHftFFjpoMz69IuhP/nL25pJfao/amoPI527KnuhFm01g==",
|
||||
"version": "4.7.4",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.4.tgz",
|
||||
"integrity": "sha512-wh+OkeF0rAVCrABWQBaEjLfb7DVPotMbu0cgWgyR0v6eA4EoVnAwcIeIbcdTE3GT/H3kbdLl7OoH2+asoDRIIg==",
|
||||
"requires": {
|
||||
"@socket.io/component-emitter": "~3.1.0",
|
||||
"debug": "~4.3.2",
|
||||
"engine.io-client": "~6.2.3",
|
||||
"socket.io-parser": "~4.2.1"
|
||||
"engine.io-client": "~6.5.2",
|
||||
"socket.io-parser": "~4.2.4"
|
||||
}
|
||||
},
|
||||
"socket.io-parser": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.2.tgz",
|
||||
"integrity": "sha512-DJtziuKypFkMMHCm2uIshOYC7QaylbtzQwiMYDuCKy3OPkjLzu4B2vAhTlqipRHHzrI0NJeBAizTK7X+6m1jVw==",
|
||||
"version": "4.2.4",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz",
|
||||
"integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==",
|
||||
"requires": {
|
||||
"@socket.io/component-emitter": "~3.1.0",
|
||||
"debug": "~4.3.1"
|
||||
|
|
Loading…
Reference in New Issue