From 65c58b28d17bb1342e4d77dd6cf15074203a4bd6 Mon Sep 17 00:00:00 2001 From: Lewis Barnes Date: Fri, 25 Mar 2022 11:59:03 +0000 Subject: [PATCH 1/3] Added support for custom network configuration. --- src/config.spec.ts | 40 ----------------- src/config.ts | 38 ---------------- src/core/NearWalletSelector.tsx | 6 +-- src/interfaces/Options.ts | 5 ++- src/network.spec.ts | 72 +++++++++++++++++++++++++++++++ src/network.ts | 55 +++++++++++++++++++++++ src/wallets/browser/NearWallet.ts | 25 ++++++++++- 7 files changed, 157 insertions(+), 84 deletions(-) delete mode 100644 src/config.spec.ts delete mode 100644 src/config.ts create mode 100644 src/network.spec.ts create mode 100644 src/network.ts diff --git a/src/config.spec.ts b/src/config.spec.ts deleted file mode 100644 index fdaee5586..000000000 --- a/src/config.spec.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { NetworkId } from "./interfaces/Options"; -import getConfig from "./config"; - -describe("config", () => { - it("returns the correct config for 'mainnet'", () => { - const networkId: NetworkId = "mainnet"; - const config = getConfig(networkId); - - expect(config).toEqual({ - networkId, - nodeUrl: "https://rpc.mainnet.near.org", - walletUrl: "https://wallet.near.org", - helperUrl: "https://helper.mainnet.near.org", - }); - }); - - it("returns the correct config for 'testnet'", () => { - const networkId: NetworkId = "testnet"; - const config = getConfig(networkId); - - expect(config).toEqual({ - networkId, - nodeUrl: "https://rpc.testnet.near.org", - walletUrl: "https://wallet.testnet.near.org", - helperUrl: "https://helper.testnet.near.org", - }); - }); - - it("returns the correct config for 'betanet'", () => { - const networkId: NetworkId = "betanet"; - const config = getConfig(networkId); - - expect(config).toEqual({ - networkId, - nodeUrl: "https://rpc.betanet.near.org", - walletUrl: "https://wallet.betanet.near.org", - helperUrl: "https://helper.betanet.near.org", - }); - }); -}); diff --git a/src/config.ts b/src/config.ts deleted file mode 100644 index 595fb2eee..000000000 --- a/src/config.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { NetworkId } from "./interfaces/Options"; - -export interface NetworkConfiguration { - networkId: NetworkId; - nodeUrl: string; - walletUrl: string; - helperUrl: string; -} - -const getConfig = (networkId: NetworkId): NetworkConfiguration => { - switch (networkId) { - case "mainnet": - return { - networkId, - nodeUrl: "https://rpc.mainnet.near.org", - walletUrl: "https://wallet.near.org", - helperUrl: "https://helper.mainnet.near.org", - }; - case "testnet": - return { - networkId, - nodeUrl: "https://rpc.testnet.near.org", - walletUrl: "https://wallet.testnet.near.org", - helperUrl: "https://helper.testnet.near.org", - }; - case "betanet": - return { - networkId, - nodeUrl: "https://rpc.betanet.near.org", - walletUrl: "https://wallet.betanet.near.org", - helperUrl: "https://helper.betanet.near.org", - }; - default: - throw Error(`Failed to find config for: '${networkId}'`); - } -}; - -export default getConfig; diff --git a/src/core/NearWalletSelector.tsx b/src/core/NearWalletSelector.tsx index 1032fa7fb..1b5c8af31 100644 --- a/src/core/NearWalletSelector.tsx +++ b/src/core/NearWalletSelector.tsx @@ -7,7 +7,7 @@ import WalletController, { import Contract from "./Contract"; import Modal from "../modal/Modal"; import EventHandler, { Emitter, EventList } from "../utils/EventsHandler"; -import getConfig from "../config"; +import { resolveNetwork } from "../network"; import ProviderService from "../services/provider/ProviderService"; import { updateState } from "../state/State"; import { MODAL_ELEMENT_ID } from "../constants"; @@ -22,10 +22,10 @@ export default class NearWalletSelector { contract: Contract; constructor(options: Options) { - const config = getConfig(options.networkId); + const network = resolveNetwork(options.networkId, options.network); const emitter = new EventHandler(); - const provider = new ProviderService(config.nodeUrl); + const provider = new ProviderService(network.nodeUrl); const controller = new WalletController(options, provider, emitter); const contract = new Contract(options, provider, controller); diff --git a/src/interfaces/Options.ts b/src/interfaces/Options.ts index 64c8de4d4..bac962e92 100644 --- a/src/interfaces/Options.ts +++ b/src/interfaces/Options.ts @@ -1,10 +1,13 @@ +import { NetworkConfiguration } from "../network"; + export type BuiltInWalletId = "near-wallet" | "sender-wallet" | "ledger-wallet"; -export type NetworkId = "mainnet" | "betanet" | "testnet"; +export type NetworkId = "mainnet" | "betanet" | "testnet" | "customnet"; export type Theme = "dark" | "light" | "auto"; export interface Options { wallets: Array; networkId: NetworkId; + network?: NetworkConfiguration; contract: { contractId: string; methodNames?: Array; diff --git a/src/network.spec.ts b/src/network.spec.ts new file mode 100644 index 000000000..2b63ed542 --- /dev/null +++ b/src/network.spec.ts @@ -0,0 +1,72 @@ +import { getNetwork, NetworkConfiguration, resolveNetwork } from "./network"; + +describe("getNetwork", () => { + it("returns the correct config for 'mainnet'", () => { + const networkId = "mainnet"; + const config = getNetwork(networkId); + + expect(config).toEqual({ + networkId, + nodeUrl: "https://rpc.mainnet.near.org", + helperUrl: "https://helper.mainnet.near.org", + explorerUrl: "https://explorer.near.org", + restApiUrl: "https://rest.nearapi.org", + }); + }); + + it("returns the correct config for 'testnet'", () => { + const networkId = "testnet"; + const config = getNetwork(networkId); + + expect(config).toEqual({ + networkId, + nodeUrl: "https://rpc.testnet.near.org", + helperUrl: "https://helper.testnet.near.org", + explorerUrl: "https://explorer.testnet.near.org", + restApiUrl: "https://rest.nearapi.org", + }); + }); + + it("returns the correct config for 'betanet'", () => { + const networkId = "betanet"; + const config = getNetwork(networkId); + + expect(config).toEqual({ + networkId, + nodeUrl: "https://rpc.betanet.near.org", + helperUrl: "https://helper.betanet.near.org", + explorerUrl: "https://explorer.betanet.near.org", + restApiUrl: "https://rest.nearapi.org", + }); + }); + + it("throws for 'customnet'", () => { + const networkId = "customnet"; + + expect(() => getNetwork(networkId)).toThrowError( + new Error(`Failed to find network configuration for '${networkId}'`) + ); + }); +}); + +describe("resolveNetwork", () => { + it("resolves to custom network configuration for 'customnet'", () => { + const network: NetworkConfiguration = { + networkId: "localnet", + nodeUrl: "http://127.0.0.1:52993", + helperUrl: "http://127.0.0.1:52997", + explorerUrl: "http://127.0.0.1:53009", + restApiUrl: "https://rest.nearapi.org", + }; + + expect(resolveNetwork("customnet", network)).toEqual(network); + }); + + it("throws if no custom network configuration is defined for 'customnet'", () => { + const networkId = "customnet"; + + expect(() => resolveNetwork(networkId)).toThrowError( + new Error(`You must define network configuration for '${networkId}'`) + ); + }); +}); diff --git a/src/network.ts b/src/network.ts new file mode 100644 index 000000000..0951006dd --- /dev/null +++ b/src/network.ts @@ -0,0 +1,55 @@ +import { NetworkId } from "./interfaces/Options"; + +export interface NetworkConfiguration { + networkId: string; + nodeUrl: string; + helperUrl: string; + explorerUrl: string; + restApiUrl: string; +} + +export const getNetwork = (networkId: NetworkId): NetworkConfiguration => { + switch (networkId) { + case "mainnet": + return { + networkId, + nodeUrl: "https://rpc.mainnet.near.org", + helperUrl: "https://helper.mainnet.near.org", + explorerUrl: "https://explorer.near.org", + restApiUrl: "https://rest.nearapi.org", + }; + case "testnet": + return { + networkId, + nodeUrl: "https://rpc.testnet.near.org", + helperUrl: "https://helper.testnet.near.org", + explorerUrl: "https://explorer.testnet.near.org", + restApiUrl: "https://rest.nearapi.org", + }; + case "betanet": + return { + networkId, + nodeUrl: "https://rpc.betanet.near.org", + helperUrl: "https://helper.betanet.near.org", + explorerUrl: "https://explorer.betanet.near.org", + restApiUrl: "https://rest.nearapi.org", + }; + default: + throw Error(`Failed to find network configuration for '${networkId}'`); + } +}; + +export const resolveNetwork = ( + networkId: NetworkId, + network?: NetworkConfiguration +): NetworkConfiguration => { + if (networkId === "customnet") { + if (!network) { + throw new Error("You must define network configuration for 'customnet'"); + } + + return network; + } + + return getNetwork(networkId); +}; diff --git a/src/wallets/browser/NearWallet.ts b/src/wallets/browser/NearWallet.ts index 3fa0a9880..73742f477 100644 --- a/src/wallets/browser/NearWallet.ts +++ b/src/wallets/browser/NearWallet.ts @@ -1,6 +1,6 @@ import { WalletConnection, connect, keyStores } from "near-api-js"; -import getConfig from "../../config"; +import { NetworkConfiguration, resolveNetwork } from "../../network"; import { Options } from "../../interfaces/Options"; import { Emitter } from "../../utils/EventsHandler"; import { logger } from "../../services/logging.service"; @@ -39,11 +39,32 @@ class NearWallet implements BrowserWallet { return true; }; + private getWalletUrl(network: NetworkConfiguration) { + switch (network.networkId) { + case "mainnet": + return "https://wallet.near.org"; + case "testnet": + return "https://wallet.testnet.near.org"; + case "betanet": + return "https://wallet.betanet.near.org"; + default: + // TODO: Make this a parameter once we have wallet modules. + return "https://wallet.testnet.near.org"; + } + } + init = async () => { + const network = resolveNetwork( + this.options.networkId, + this.options.network + ); const keyStore = new keyStores.BrowserLocalStorageKeyStore(); const near = await connect({ keyStore, - ...getConfig(this.options.networkId), + networkId: network.networkId, + nodeUrl: network.nodeUrl, + helperUrl: network.helperUrl, + walletUrl: this.getWalletUrl(network), headers: {}, }); From fb5521e8b034ca2ad036ca87aea53ac40356116b Mon Sep 17 00:00:00 2001 From: Lewis Barnes Date: Fri, 25 Mar 2022 12:06:19 +0000 Subject: [PATCH 2/3] Updated docs. --- README.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 936506b5f..b46067f98 100644 --- a/README.md +++ b/README.md @@ -41,14 +41,24 @@ const selector = new NearWalletSelector({ ```ts type BuiltInWalletId = "near-wallet" | "sender-wallet" | "ledger-wallet"; -type NetworkId = "mainnet" | "betanet" | "testnet"; +type NetworkId = "mainnet" | "betanet" | "testnet" | "customnet"; type Theme = "dark" | "light" | "auto"; +interface NetworkConfiguration { + networkId: string; + nodeUrl: string; + helperUrl: string; + explorerUrl: string; + restApiUrl: string; +} + interface Options { // List of wallets you want to support in your dApp. wallets: Array; // Network ID matching that of your dApp. networkId: NetworkId; + // Required when networkId is 'customnet'. + network?: NetworkConfiguration; contract: { // Account ID of the Smart Contract used for 'view' and 'signAndSendTransaction' calls. contractId: string; From ab615ec9b53df5c38ead9d6300d6c760d6908c23 Mon Sep 17 00:00:00 2001 From: Lewis Barnes Date: Fri, 25 Mar 2022 12:16:55 +0000 Subject: [PATCH 3/3] Added another test for resolveNetwork. --- src/network.spec.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/network.spec.ts b/src/network.spec.ts index 2b63ed542..0d280ab4d 100644 --- a/src/network.spec.ts +++ b/src/network.spec.ts @@ -50,6 +50,12 @@ describe("getNetwork", () => { }); describe("resolveNetwork", () => { + it("resolves to network configuration matching the preset", () => { + const networkId = "testnet"; + + expect(resolveNetwork(networkId)).toEqual(getNetwork(networkId)); + }); + it("resolves to custom network configuration for 'customnet'", () => { const network: NetworkConfiguration = { networkId: "localnet",