diff --git a/src/pages/bridge/BridgeOut.tsx b/src/pages/bridge/BridgeOut.tsx index ffad5258..b62c2776 100644 --- a/src/pages/bridge/BridgeOut.tsx +++ b/src/pages/bridge/BridgeOut.tsx @@ -258,7 +258,8 @@ const BridgeOut = (props: BridgeOutProps) => { bridgeOutNetwork.latestBlockEndpoint, ibcFee, chain, - memo + memo, + bridgeOutNetwork.extraEndpoints ), BridgeTransactionType.BRIDGE_OUT, bridgeTxStore.setTransactionStatus, diff --git a/src/pages/bridge/config/bridgeOutNetworks.ts b/src/pages/bridge/config/bridgeOutNetworks.ts index cfebfee0..64e84267 100644 --- a/src/pages/bridge/config/bridgeOutNetworks.ts +++ b/src/pages/bridge/config/bridgeOutNetworks.ts @@ -11,6 +11,7 @@ export interface BridgeOutNetworkInfo { channel: string; endpoint: string; latestBlockEndpoint?: string; + extraEndpoints?: string[]; addressBeginning: string; checkAddress: (address: string) => boolean; } @@ -48,6 +49,7 @@ export const ALL_BRIDGE_OUT_NETWORKS: BridgeOutNetworkData = { ], channel: "channel-0", endpoint: "https://gravitychain.io:1317", + extraEndpoints: ["https://gravity-api.polkachu.com"], addressBeginning: "gravity", checkAddress: function (address) { return addressCheck(address, this.addressBeginning); diff --git a/src/pages/bridge/utils/IBC/IBCTransfer.ts b/src/pages/bridge/utils/IBC/IBCTransfer.ts index bc40fc0e..9553119a 100644 --- a/src/pages/bridge/utils/IBC/IBCTransfer.ts +++ b/src/pages/bridge/utils/IBC/IBCTransfer.ts @@ -16,7 +16,8 @@ export async function txIBCTransfer( latestBlockEndpoint: any, fee: any, chain: any, - memo: any + memo: any, + extraEndpoints?: string[] ) { // check metamask //@ts-ignore @@ -33,10 +34,10 @@ export async function txIBCTransfer( const account = accounts[0]; const senderObj = await getSenderObj(account, nodeAddressIP); //get revision number/height for construction of the timeout-height object (determines the last update of the counter-party IBC client) - const ibcData = await getIBCData(counterPartyChain); - + const ibcData = await getIBCData(counterPartyChain, extraEndpoints); let timeoutTimestamp = await getBlockTimestamp( counterPartyChain, + extraEndpoints, latestBlockEndpoint ); @@ -70,15 +71,53 @@ export async function txIBCTransfer( ); } -export async function getIBCData(nodeAddress: string) { - const resp = await fetch(nodeAddress + generateEndpointIBCChannels(), { - method: "GET", - headers: { - Accept: "application/json", - }, - }).catch((error) => console.log("getIBCData::error: ", error)); - //@ts-ignore - return resp.json(); +async function tryEndpoint(endpoint: string) { + try { + const res = await fetch(endpoint, { + method: "GET", + headers: { + Accept: "application/json", + }, + }); + if (res.ok) { + return [await res.json(), true]; + } else { + return [null, false]; + } + } catch (err) { + console.error(err); + return [null, false]; + } +} +async function tryMultipleEndpoints( + allEndpoints: string[], + endpointAddon: string +) { + let endpointUp = false; + let data = null; + let endpointAttempt = 0; + while (!endpointUp && endpointAttempt < allEndpoints.length) { + const [endpointData, okay] = await tryEndpoint( + allEndpoints[endpointAttempt] + endpointAddon + ); + endpointAttempt++; + endpointUp = okay; + data = endpointData; + } + return data; +} + +export async function getIBCData( + nodeAddress: string, + extraEndpoints?: string[] +) { + const allEndpoints = extraEndpoints + ? [nodeAddress, ...extraEndpoints] + : [nodeAddress]; + return await tryMultipleEndpoints( + allEndpoints, + generateEndpointIBCChannels() + ); } /** @@ -86,21 +125,33 @@ export async function getIBCData(nodeAddress: string) { */ export async function getBlockTimestamp( nodeAddress: string, + extraEndpoints?: string[], latestBlockEndpoint?: string ) { const urlEnding = latestBlockEndpoint ?? ""; - const resp = await fetch(nodeAddress + urlEnding + "/blocks/latest", { - method: "GET", - headers: { - Accept: "application/json", - }, - }).catch((error) => console.log("getBlockTimestamp::error: ", error)); - //@ts-ignore - const obj = await resp.json(); - // get iso formatted time stamp from latest block - const ts = obj["block"]["header"]["time"]; - // parse string into microseconds UTC - const ms = Date.parse(ts); - // return as nano-seconds - return Number(ms * 1e7 + 600 * 1e9).toString(); + const allEndpoints = extraEndpoints + ? [nodeAddress, ...extraEndpoints] + : [nodeAddress]; + const data = await tryMultipleEndpoints( + allEndpoints, + urlEnding + "/blocks/latest" + ); + // const resp = await fetch(nodeAddress + urlEnding + "/blocks/latest", { + // method: "GET", + // headers: { + // Accept: "application/json", + // }, + // }).catch((error) => console.log("getBlockTimestamp::error: ", error)); + // //@ts-ignore + // const obj = await resp.json(); + + if (data) { + // get iso formatted time stamp from latest block + const ts = data["block"]["header"]["time"]; + // parse string into microseconds UTC + const ms = Date.parse(ts); + // return as nano-seconds + return Number(ms * 1e7 + 600 * 1e9).toString(); + } + throw Error("no timestamp"); } diff --git a/src/pages/bridge/walkthrough/managers/BridgeOutManager.tsx b/src/pages/bridge/walkthrough/managers/BridgeOutManager.tsx index fcf0f535..ed6f0562 100644 --- a/src/pages/bridge/walkthrough/managers/BridgeOutManager.tsx +++ b/src/pages/bridge/walkthrough/managers/BridgeOutManager.tsx @@ -198,7 +198,8 @@ export const BridgeOutManager = (props: BridgeOutManagerProps) => { props.currentBridgeOutNetwork.latestBlockEndpoint, ibcFee, chain, - memo + memo, + props.currentBridgeOutNetwork.extraEndpoints ), BridgeTransactionType.BRIDGE_OUT, props.setCosmosTxStatus,