From 242975123e3759953717929dbb90293d4c8191dd Mon Sep 17 00:00:00 2001 From: Samuel Manzanera Date: Fri, 18 Oct 2024 14:52:54 +0200 Subject: [PATCH] fix: :bug: Remove nearest endpoints fetching The nearest endpoints fetching created problems when dApps on https call directly a node which are not. Then we can "Cannot reach Archethic node" This fix uses the single endpoint passed as parameter of the Archethic's constructor --- src/api.ts | 20 +++--- src/api/wallet_rpc.ts | 3 - src/endpoint.ts | 2 - src/index.ts | 29 +++------ src/transaction_sender.ts | 2 +- tests/index.test.ts | 128 -------------------------------------- 6 files changed, 18 insertions(+), 166 deletions(-) diff --git a/src/api.ts b/src/api.ts index 828acc3..6fa1648 100644 --- a/src/api.ts +++ b/src/api.ts @@ -9,7 +9,7 @@ import Transaction from "./transaction.js"; * @param query * @param endpoint */ -export async function rawGraphQLQuery(query: string, endpoint: string): Promise { +export async function rawGraphQLQuery(query: string, endpoint: string | URL): Promise { const url = new URL("/api", endpoint); return fetch(url, { method: "POST", @@ -36,7 +36,7 @@ export async function rawGraphQLQuery(query: string, endpoint: string): Promise< * @param endpoint The Archethic API endpoint * @returns {Promise} A list of nearest endpoints */ -export async function getNearestEndpoints(endpoint: string): Promise { +export async function getNearestEndpoints(endpoint: string | URL): Promise { const url = new URL("/api", endpoint); return fetch(url, { method: "POST", @@ -68,7 +68,7 @@ export async function getNearestEndpoints(endpoint: string): Promise { +export async function getTransactionIndex(address: string | Uint8Array, endpoint: string | URL): Promise { address = maybeUint8ArrayToHex(address); const url = new URL("/api", endpoint); @@ -101,7 +101,7 @@ export async function getTransactionIndex(address: string | Uint8Array, endpoint * @param endpoint The Archethic API endpoint * @returns {Promise} The balance of the address */ -export async function getStorageNoncePublicKey(endpoint: string): Promise { +export async function getStorageNoncePublicKey(endpoint: string | URL): Promise { const url = new URL("/api", endpoint); return fetch(url, { method: "POST", @@ -136,7 +136,7 @@ export async function getStorageNoncePublicKey(endpoint: string): Promise { address = maybeUint8ArrayToHex(address); @@ -180,7 +180,7 @@ export async function getTransactionOwnerships( * @param tokenAddress address of the token * @param endpoint The Archethic API endpoint */ -export async function getToken(tokenAddress: string | Uint8Array, endpoint: string): Promise<{} | Token> { +export async function getToken(tokenAddress: string | Uint8Array, endpoint: string | URL): Promise<{} | Token> { tokenAddress = maybeUint8ArrayToHex(tokenAddress); const url = new URL("/api", endpoint); @@ -214,7 +214,7 @@ export async function getToken(tokenAddress: string | Uint8Array, endpoint: stri * @param endpoint The Archethic API endpoint * @param timestamp The timestamp of the data to get */ -export async function getOracleData(endpoint: string, timestamp: undefined | number = undefined): Promise { +export async function getOracleData(endpoint: string | URL, timestamp: undefined | number = undefined): Promise { let query; if (timestamp === undefined) { @@ -268,7 +268,7 @@ export async function getOracleData(endpoint: string, timestamp: undefined | num * @param endpoint The Archethic API endpoint * @param handler The handler to call when a new update is received */ -export async function subscribeToOracleUpdates(endpoint: string, handler: Function): Promise { +export async function subscribeToOracleUpdates(endpoint: string | URL, handler: Function): Promise { const { host, protocol } = new URL(endpoint); const ws_protocol = protocol == "https:" ? "wss" : "ws"; @@ -299,7 +299,7 @@ export async function subscribeToOracleUpdates(endpoint: string, handler: Functi * @param endpoint The Archethic API endpoint * @param address The address to get the balance of */ -export async function getBalance(address: string | Uint8Array, endpoint: string): Promise { +export async function getBalance(address: string | Uint8Array, endpoint: string | URL): Promise { address = maybeUint8ArrayToHex(address); const url = new URL("/api", endpoint); @@ -332,7 +332,7 @@ export async function getBalance(address: string | Uint8Array, endpoint: string) }); } -export async function getContractCode(address: string | Uint8Array, endpoint: string): Promise { +export async function getContractCode(address: string | Uint8Array, endpoint: string | URL): Promise { address = maybeUint8ArrayToHex(address); const url = new URL("/api", endpoint); diff --git a/src/api/wallet_rpc.ts b/src/api/wallet_rpc.ts index b21fbc7..db13b25 100644 --- a/src/api/wallet_rpc.ts +++ b/src/api/wallet_rpc.ts @@ -88,7 +88,6 @@ export class ArchethicWalletClient { _dispatchConnectionState(state?: ConnectionState) { const connectionState = state ?? this.connectionState - console.log(`Connection state updated : ${connectionState}`); this._connectionStateEventTarget.dispatchEvent(new Event(connectionState)); } @@ -100,8 +99,6 @@ export class ArchethicWalletClient { */ async connect(): Promise { return new Promise(async (resolve, reject) => { - console.log('Connection attempt'); - if (this.connectionState != ConnectionState.Closed) { return reject(new Error("Connection already established. Cancelling new connection request")); } diff --git a/src/endpoint.ts b/src/endpoint.ts index a2ab623..7bbdb6e 100644 --- a/src/endpoint.ts +++ b/src/endpoint.ts @@ -17,7 +17,6 @@ export class EndpointFactory { */ build(endpoint: string | undefined): Endpoint { if (endpoint === undefined) { - console.log('Using AWC client'); return new AWCEndpoint( AWCWebBrowserExtension.awc ?? new ArchethicWalletClient(new AWCWebsocketStreamChannel(`ws://localhost:12345`)) @@ -26,7 +25,6 @@ export class EndpointFactory { const url: URL = new URL(endpoint); if (url.protocol === "http:" || url.protocol === "https:") { - console.log('Using direct endpoint'); return new DirectEndpoint(endpoint); } diff --git a/src/index.ts b/src/index.ts index 74c0f71..983533b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -26,7 +26,6 @@ export default class Archethic { rpcWallet: ArchethicWalletClient | undefined; rpcNode: NodeRPCClient | undefined; transaction: Transaction; - nearestEndpoints: Set; account: Account; network: Network; @@ -40,7 +39,6 @@ export default class Archethic { } this.account = new Account(this); this.network = new Network(this); - this.nearestEndpoints = new Set(); this.transaction = new Transaction(this); this.rpcNode = new NodeRPCClient(this); } @@ -49,32 +47,19 @@ export default class Archethic { if (this.endpoint instanceof AWCEndpoint) { await this.endpoint.resolve(); } - const nodes = this.endpoint.nodeEndpoint === null ? - [] : - await Api.getNearestEndpoints(this.endpoint.nodeEndpoint.toString()); - - let nearestEndpoints = nodes.map(({ ip, port }) => { - return `http://${ip}:${port}`; - }); - - nearestEndpoints.push(this.endpoint.origin.toString()); // Add the main endpoint as fallback - - this.nearestEndpoints = new Set(nearestEndpoints); return this; } - async requestNode(call: (endpoint: string) => Promise): Promise { - const node = this.nearestEndpoints.values().next().value; + async requestNode(call: (endpoint: URL) => Promise): Promise { + if (!this.endpoint.nodeEndpoint) { + throw new Error("Archethic node's endpoint is undefined"); + } try { - return await call(node); + return await call(this.endpoint.nodeEndpoint); } catch (err) { - this.nearestEndpoints.delete(node); - if (this.nearestEndpoints.size == 0) { - console.log(err); - throw new Error("Cannot reach Archethic node"); - } - return this.requestNode(call); + console.log(err); + throw new Error("Cannot reach Archethic node"); } } } diff --git a/src/transaction_sender.ts b/src/transaction_sender.ts index ebb976a..02055d5 100644 --- a/src/transaction_sender.ts +++ b/src/transaction_sender.ts @@ -78,7 +78,7 @@ export default class TransactionSender { async send( tx: TransactionBuilder, - endpoint: string, + endpoint: string | URL, confirmationThreshold: number = 100, timeout: number = 60 ): Promise { diff --git a/tests/index.test.ts b/tests/index.test.ts index 68c341d..6265a46 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -14,132 +14,4 @@ describe("Archethic", () => { expect(archethic.transaction).not.toBeUndefined(); }); - describe("connect", () => { - it("should request endpoint to get list of nearest nodes", async () => { - nock("http://localhost:4000", {}) - .post("/api", { - query: `query { - nearestEndpoints { - ip, - port - } - }` - }) - .reply(200, { - data: { - nearestEndpoints: [ - { ip: "localhost", port: 4000 }, - { ip: "30.193.101.100", port: 40000 } - ] - } - }); - - const archethic = new Archethic("http://localhost:4000"); - await archethic.connect(); - - expect(archethic.nearestEndpoints).toStrictEqual( - new Set(["http://localhost:4000", "http://30.193.101.100:40000"]) - ); - }); - }); - - describe("requestNode", () => { - it("should request the first nearest node", async () => { - nock("http://localhost:4000", {}) - .post("/api", { - query: `query { - nearestEndpoints { - ip, - port - } - }` - }) - .reply(200, { - data: { - nearestEndpoints: [ - { ip: "localhost", port: 4000 }, - { ip: "30.193.101.100", port: 40000 } - ] - } - }); - const archethic = new Archethic("http://localhost:4000"); - await archethic.connect(); - - nock("http://localhost:4000", {}) - .post("/api", { - query: `query { - sharedSecrets { - storageNoncePublicKey - } - }` - }) - .reply(200, { - data: { - sharedSecrets: { - storageNoncePublicKey: "publicKey" - } - } - }); - - const publicKey = await archethic.requestNode((endpoint) => { - return API.getStorageNoncePublicKey(endpoint); - }); - - expect(publicKey).toBe("publicKey"); - }); - - it("should request the next nearest node when the first failed", async () => { - nock("http://localhost:4000", {}) - .post("/api", { - query: `query { - nearestEndpoints { - ip, - port - } - }` - }) - .reply(200, { - data: { - nearestEndpoints: [ - { ip: "localhost", port: 4000 }, - { ip: "30.193.101.100", port: 40000 } - ] - } - }); - const archethic = new Archethic("http://localhost:4000"); - await archethic.connect(); - - nock("http://localhost:4000", {}) - .post("/api", { - query: `query { - sharedSecrets { - storageNoncePublicKey - } - }` - }) - .reply(500, "Internal Server Error"); - - nock("http://30.193.101.100:40000", {}) - .post("/api", { - query: `query { - sharedSecrets { - storageNoncePublicKey - } - }` - }) - .reply(200, { - data: { - sharedSecrets: { - storageNoncePublicKey: "publicKey" - } - } - }); - - const publicKey = await archethic.requestNode((endpoint) => { - return API.getStorageNoncePublicKey(endpoint); - }); - - expect(publicKey).toBe("publicKey"); - }); - }); });