From 38382c021296305c8667db12beddf92ccdc4b6cd Mon Sep 17 00:00:00 2001 From: Tyler Hall Date: Fri, 7 Feb 2025 05:22:20 +0000 Subject: [PATCH] feat(connect)!: remove connect.hb. Add modes and corresponding *_URL args to connect() --- connect/package.json | 2 +- connect/src/hb.playground.js | 7 +- connect/src/index.browser.js | 18 +- connect/src/index.common.js | 390 ++++++++++++++++++++--------------- connect/src/index.js | 19 +- connect/src/index.test.js | 52 +++++ 6 files changed, 311 insertions(+), 177 deletions(-) create mode 100644 connect/src/index.test.js diff --git a/connect/package.json b/connect/package.json index 85478d2c4..d37e11b7c 100644 --- a/connect/package.json +++ b/connect/package.json @@ -40,7 +40,7 @@ "build": "npm run build:types && npm run build:src", "build:src": "node esbuild.js", "build:types": "tsc src/index.js --skipLibCheck --declaration --allowJs --emitDeclarationOnly --outDir dist", - "test": "node --test ./src/**/*.test.js", + "test": "node --test ./src/**/*.test.js src/index.test.js", "pretest:integration": "npm run build && npm link", "test:integration": "cd ./test/e2e && npm test" }, diff --git a/connect/src/hb.playground.js b/connect/src/hb.playground.js index 6fd157778..477b7729f 100644 --- a/connect/src/hb.playground.js +++ b/connect/src/hb.playground.js @@ -11,7 +11,7 @@ import { tap } from 'ramda' import { connect } from './index.js' -describe('index - node', () => { +describe('hb playground', () => { /** * Generate a wallet in a temporary directory prior to running the tests */ @@ -30,9 +30,10 @@ describe('index - node', () => { test('should relay the message through HyperBEAM', async () => { const wallet = JSON.parse(readFileSync(tmpWallet).toString()) - const { spawn, message, result, createDataItemSigner } = connect.hb({ + const { spawn, message, result, createDataItemSigner } = connect({ + MODE: 'mainnet', wallet, - URL: process.env.HB_URL || 'http://localhost:8734' + AO_URL: process.env.AO_URL || 'http://localhost:8734' }) const p = await spawn({ diff --git a/connect/src/index.browser.js b/connect/src/index.browser.js index 2d056ce9c..072c9591e 100644 --- a/connect/src/index.browser.js +++ b/connect/src/index.browser.js @@ -9,25 +9,33 @@ const GRAPHQL_URL = globalThis.GRAPHQL_URL || undefined const GRAPHQL_MAX_RETRIES = globalThis.GRAPHQL_MAX_RETRIES || undefined const GRAPHQL_RETRY_BACKOFF = globalThis.GRAPHQL_RETRY_BACKOFF || undefined -const HB_URL = globalThis.HB_URL || undefined +const RELAY_URL = globalThis.RELAY_URL || undefined +const AO_URL = globalThis.AO_URL = undefined const connect = connectWith({ createDataItemSigner: WalletClient.createDataItemSigner, createHbSigner: WalletClient.createHbSigner }) +/** + * hardcoded to legacy, since wallet is not provided here + * + * TODO: probably remove these at the top level, and require using connect + * so as to set the mode and provide the wallet + */ const { result, results, message, spawn, monitor, unmonitor, dryrun, assign, createDataItemSigner } = connect({ + MODE: 'legacy', GATEWAY_URL, MU_URL, CU_URL, + RELAY_URL, + AO_URL, GRAPHQL_URL, GRAPHQL_MAX_RETRIES, - GRAPHQL_RETRY_BACKOFF + GRAPHQL_RETRY_BACKOFF, + noLog: true }) -const originalHb = connect.hb -connect.hb = ({ URL = HB_URL, ...rest }) => originalHb({ URL, ...rest }) - export { result, results, message, spawn, monitor, unmonitor, dryrun, assign } export { connect } export { serializeCron } diff --git a/connect/src/index.common.js b/connect/src/index.common.js index b49800197..20b000e32 100644 --- a/connect/src/index.common.js +++ b/connect/src/index.common.js @@ -24,9 +24,10 @@ const DEFAULT_CU_URL = 'https://cu.ao-testnet.xyz' /** * TODO: set this when we know it */ -const DEFAULT_HB_URL = 'http://localhost:8734' -const DEFAULT_HB_CU_URL = 'http://cu.s451-comm3-main.xyz' -const DEFAULT_HB_MU_URL = 'http://mu.s451-comm3-main.xyz' +const DEFAULT_RELAY_URL = 'http://137.220.36.155:8734' +const DEFAULT_AO_URL = 'http://137.220.36.155:8734' +const DEFAULT_RELAY_CU_URL = 'http://cu.s451-comm3-main.xyz' +const DEFAULT_RELAY_MU_URL = 'http://mu.s451-comm3-main.xyz' const defaultFetch = fetch @@ -36,60 +37,44 @@ export { serializeCron } from './lib/serializeCron/index.js' * @param {{ createDataItemSigner: (wallet:any) => Types['signer'], createHbSigner: any }} */ export function connectWith ({ createDataItemSigner, createHbSigner }) { - const logger = createLogger() + const _logger = createLogger() /** - * Build the sdk apis using the provided ao component urls. You can currently specify - * - * - a GATEWAY_URL - * - a GRAPHQL_URL (defaults to GATEWAY_URL/graphql) - * - a GRAPHQL_MAX_RETRIES. Defaults to 0 - * - a GRAPHQL_RETRY_BACKOFF. Defaults to 300 (moot if GRAPHQL_MAX_RETRIES is set to 0) - * - a Messenger Unit URL - * - a Compute Unit URL - * - * If any value is not provided, an SDK default will be used. - * Invoking connect() with no parameters or an empty object is functionally equivalent - * to using the top-lvl exports of the SDK ie. - * - * @example - * import { - * spawn, - * message, - * result, - * results, - * monitor, - * connect - * } from '@permaweb/ao-sdk'; - * - * // These are functionally equivalent - * connect() == { spawn, message, result, results, monitor } + * Run connect in HyperBEAM mode, relaying network calls through the configured + * HyperBEAM node. * - * @typedef Services - * @property {string} [GATEWAY_URL] - the url of the desried Gateway. - * @property {string} [GRAPHQL_URL] - the url of the desired Arweave Gateway GraphQL Server - * @property {number} [GRAPHQL_MAX_RETRIES] - the number of times to retry querying the gateway, utilizing an exponential backoff - * @property {number} [GRAPHQL_RETRY_BACKOFF] - the initial backoff, in milliseconds (moot if GRAPHQL_MAX_RETRIES is set to 0) - * @property {string} [MU_URL] - the url of the desried ao Messenger Unit. - * @property {string} [CU_URL] - the url of the desried ao Compute Unit. + * @typedef HyperBeam + * @property {any} wallet - the wallet to use to sign HyperBEAM HTTP messages + * @property {string} [RELAY_URL] the HyperBEAM node * - * @param {Services} [services] + * @param {Services & HyperBeam} args + * @returns {Omit, 'createDataItemSigner'> & { createDataItemSigner: () => Types['signer'] }} */ - function connect ({ + function relayMode ({ + MODE, + wallet, GRAPHQL_URL, GRAPHQL_MAX_RETRIES, GRAPHQL_RETRY_BACKOFF, - GATEWAY_URL = DEFAULT_GATEWAY_URL, - MU_URL = DEFAULT_MU_URL, - CU_URL = DEFAULT_CU_URL, - fetch = defaultFetch, - /** - * Only set when augmented with connect.hb(), - * and so default to the provided fetch otherwise. - */ - originalFetch = fetch - } = {}) { - if (!GRAPHQL_URL) GRAPHQL_URL = joinUrl({ url: GATEWAY_URL, path: '/graphql' }) + MU_URL = DEFAULT_RELAY_MU_URL, + CU_URL = DEFAULT_RELAY_CU_URL, + RELAY_URL = DEFAULT_RELAY_URL, + fetch: originalFetch = defaultFetch + }) { + const logger = _logger.child('relay') + logger('Mode Activated 🔀') + + const signer = createHbSigner(wallet) + const fetch = HbClient.relayerWith({ + /** + * Always wrap default fetch with relayer, + * no embellishment beyond the relayer + */ + fetch: defaultFetch, + logger, + HB_URL: RELAY_URL, + signer + }) const { validate } = schedulerUtilsConnect({ cacheSize: 100, GRAPHQL_URL, GRAPHQL_MAX_RETRIES, GRAPHQL_RETRY_BACKOFF }) @@ -99,21 +84,12 @@ export function connectWith ({ createDataItemSigner, createHbSigner }) { logger: resultLogger }) - /** - * default writeInteraction that works OOTB - * - writes signed data item for message to the MU - */ const messageLogger = logger.child('message') const message = messageWith({ deployMessage: MuClient.deployMessageWith({ fetch, MU_URL, logger: messageLogger }), logger: messageLogger }) - /** - * default spawn that works OOTB - * - Verifies the inputs - * - spawns the process via the MU - */ const spawnLogger = logger.child('spawn') const spawn = spawnWith({ loadTransactionMeta: GatewayClient.loadTransactionMetaWith({ fetch: originalFetch, GRAPHQL_URL, logger: spawnLogger }), @@ -122,49 +98,30 @@ export function connectWith ({ createDataItemSigner, createHbSigner }) { logger: spawnLogger }) - /** - * default monitor that works OOTB - * - Verifies the inputs - * - post a signed message via the MU /monitor/:process endpoint - */ const monitorLogger = logger.child('monitor') const monitor = monitorWith({ deployMonitor: MuClient.deployMonitorWith({ fetch, MU_URL, logger: monitorLogger }), logger: monitorLogger }) - /** - * default unmonitor that works OOTB - * - Verifies the inputs - * - post a signed message via the MU /monitor/:process endpoint - */ const unmonitorLogger = logger.child('unmonitor') const unmonitor = unmonitorWith({ deployUnmonitor: MuClient.deployUnmonitorWith({ fetch, MU_URL, logger: unmonitorLogger }), logger: monitorLogger }) - /** - * results - returns batch of Process Results given a specified range - */ const resultsLogger = logger.child('results') const results = resultsWith({ queryResults: CuClient.queryResultsWith({ fetch, CU_URL, logger: resultsLogger }), logger: resultsLogger }) - /** - * dryrun - sends a message object to the cu and returns a result - */ const dryrunLogger = logger.child('dryrun') const dryrun = dryrunWith({ dryrunFetch: CuClient.dryrunFetchWith({ fetch, CU_URL, logger: dryrunLogger }), logger: dryrunLogger }) - /** - * POSTs an Assignment to the MU - */ const assignLogger = logger.child('assign') const assign = assignWith({ deployAssign: MuClient.deployAssignWith({ @@ -175,128 +132,235 @@ export function connectWith ({ createDataItemSigner, createHbSigner }) { logger: messageLogger }) - return { result, results, message, spawn, monitor, unmonitor, dryrun, assign, createDataItemSigner } + return { MODE, result, results, message, spawn, monitor, unmonitor, dryrun, assign, createDataItemSigner } } - /** - * Run connect in HyperBEAM mode, relaying network calls through the configured - * HyperBEAM node. - * - * @typedef HyperBeam - * @property {any} wallet - the wallet to use to sign HyperBEAM HTTP messages - * @property {string} [URL] the HyperBEAM node - * - * @param {Services & HyperBeam} args - * @returns {Omit, 'createDataItemSigner'> & { createDataItemSigner: () => Types['signer'] }} - */ - connect.hb = function ({ - wallet, - URL = DEFAULT_HB_URL, - fetch: originalFetch = defaultFetch, - ...rest + function legacyMode ({ + MODE, + GRAPHQL_URL, + GRAPHQL_MAX_RETRIES, + GRAPHQL_RETRY_BACKOFF, + MU_URL = DEFAULT_MU_URL, + CU_URL = DEFAULT_CU_URL, + fetch = defaultFetch, + noLog }) { - logger('HyperBEAM mode activated! ⚡ī¸â­ī¸') + const logger = _logger.child('legacy') + if (!noLog) logger('Mode Activated ℹī¸') - let { - GRAPHQL_URL, - GRAPHQL_MAX_RETRIES, - GRAPHQL_RETRY_BACKOFF, - GATEWAY_URL = DEFAULT_GATEWAY_URL - } = rest + const { validate } = schedulerUtilsConnect({ cacheSize: 100, GRAPHQL_URL, GRAPHQL_MAX_RETRIES, GRAPHQL_RETRY_BACKOFF }) - if (!GRAPHQL_URL) GRAPHQL_URL = joinUrl({ url: GATEWAY_URL, path: '/graphql' }) + const resultLogger = logger.child('result') + const result = resultWith({ + loadResult: CuClient.loadResultWith({ fetch, CU_URL, logger: resultLogger }), + logger: resultLogger + }) - const { validate } = schedulerUtilsConnect({ - cacheSize: 100, - GRAPHQL_URL, - GRAPHQL_MAX_RETRIES, - GRAPHQL_RETRY_BACKOFF + const messageLogger = logger.child('message') + const message = messageWith({ + deployMessage: MuClient.deployMessageWith({ fetch, MU_URL, logger: messageLogger }), + logger: messageLogger }) - const signer = createHbSigner(wallet) + const spawnLogger = logger.child('spawn') + const spawn = spawnWith({ + loadTransactionMeta: GatewayClient.loadTransactionMetaWith({ fetch, GRAPHQL_URL, logger: spawnLogger }), + validateScheduler: validate, + deployProcess: MuClient.deployProcessWith({ fetch, MU_URL, logger: spawnLogger }), + logger: spawnLogger + }) + + const monitorLogger = logger.child('monitor') + const monitor = monitorWith({ + deployMonitor: MuClient.deployMonitorWith({ fetch, MU_URL, logger: monitorLogger }), + logger: monitorLogger + }) + + const unmonitorLogger = logger.child('unmonitor') + const unmonitor = unmonitorWith({ + deployUnmonitor: MuClient.deployUnmonitorWith({ fetch, MU_URL, logger: unmonitorLogger }), + logger: monitorLogger + }) + + const resultsLogger = logger.child('results') + const results = resultsWith({ + queryResults: CuClient.queryResultsWith({ fetch, CU_URL, logger: resultsLogger }), + logger: resultsLogger + }) + + const dryrunLogger = logger.child('dryrun') + const dryrun = dryrunWith({ + dryrunFetch: CuClient.dryrunFetchWith({ fetch, CU_URL, logger: dryrunLogger }), + logger: dryrunLogger + }) + + const assignLogger = logger.child('assign') + const assign = assignWith({ + deployAssign: MuClient.deployAssignWith({ + fetch, + MU_URL, + logger: assignLogger + }), + logger: messageLogger + }) + return { MODE, result, results, message, spawn, monitor, unmonitor, dryrun, assign, createDataItemSigner } + } + + function mainnetMode ({ + MODE, + wallet, + GRAPHQL_URL, + AO_URL = DEFAULT_AO_URL, + fetch = defaultFetch + }) { + const logger = _logger.child('mainnet') + logger('Mode Activated 🐲') + + if (!wallet) throw new Error('mainnet mode requires providing a wallet to connect()') + + const signer = createHbSigner(wallet) + const staticWalletDataItemSigner = () => createDataItemSigner(wallet) /** - * TODO: connect and connect.hb are increasingly diverging, - * so it would be best to allow them to diverge, instead - * of composing them, then overwriting certian apis. - * - * Eventually all apis will require a signer for hb mode, - * unlike testnet mode, and so even divergence in the public - * api will need to happen. + * TODO: implement validating a scheduler */ - const api = connect({ - ...rest, - CU_URL: rest.CU_URL || DEFAULT_HB_CU_URL, - MU_URL: rest.MU_URL || DEFAULT_HB_MU_URL, - /** - * Downstream logic, that does not need to be relayed - * may still want the original fetch, so inject it here - */ - originalFetch, - /** - * Use the HyperBEAM relay as fetch for all downstream - * dependencies - */ - fetch: HbClient.relayerWith({ - ...rest, - /** - * Always wrap default fetch with relayer, - * no embellishment beyond the relayer - */ + async function mockValidate (address) { + logger('Mock validation for address "%s"', address) + return true + } + + const resultLogger = logger.child('result') + const result = resultWith({ + loadResult: HbClient.loadResultWith({ fetch: defaultFetch, - logger, - HB_URL: URL, + logger: resultLogger, + HB_URL: AO_URL, signer - }) + }), + logger: resultLogger }) - const createDataItemSigner = api.createDataItemSigner - /** - * createDataItemSigner is restricted to only - * use the wallet configured with HyperBEAM - */ - api.createDataItemSigner = () => createDataItemSigner(wallet) - - const messageLogger = logger.child('hb:message') - api.message = messageWith({ + const messageLogger = logger.child('message') + const message = messageWith({ deployMessage: HbClient.deployMessageWith({ fetch: defaultFetch, logger: messageLogger, - HB_URL: URL, + HB_URL: AO_URL, signer }), logger: messageLogger }) - const spawnLogger = logger.child('hb:spawn') - api.spawn = spawnWith({ + const spawnLogger = logger.child('spawn') + const spawn = spawnWith({ loadTransactionMeta: GatewayClient.loadTransactionMetaWith({ - fetch: originalFetch, + fetch, GRAPHQL_URL, logger: spawnLogger }), - validateScheduler: validate, + validateScheduler: mockValidate, deployProcess: HbClient.deployProcessWith({ fetch: defaultFetch, logger: spawnLogger, - HB_URL: URL, + HB_URL: AO_URL, signer }), logger: spawnLogger }) - const resultLogger = logger.child('hb:result') - api.result = resultWith({ - loadResult: HbClient.loadResultWith({ - fetch: defaultFetch, - logger: resultLogger, - HB_URL: URL, - signer - }), - logger: resultLogger - }) + // const monitorLogger = logger.child('monitor') + // const monitor = monitorWith({ + // deployMonitor: MuClient.deployMonitorWith({ fetch, MU_URL, logger: monitorLogger }), + // logger: monitorLogger + // }) + + // const unmonitorLogger = logger.child('unmonitor') + // const unmonitor = unmonitorWith({ + // deployUnmonitor: MuClient.deployUnmonitorWith({ fetch, MU_URL, logger: unmonitorLogger }), + // logger: monitorLogger + // }) + + // const resultsLogger = logger.child('results') + // const results = resultsWith({ + // queryResults: CuClient.queryResultsWith({ fetch, CU_URL, logger: resultsLogger }), + // logger: resultsLogger + // }) + + // const dryrunLogger = logger.child('dryrun') + // const dryrun = dryrunWith({ + // dryrunFetch: CuClient.dryrunFetchWith({ fetch, CU_URL, logger: dryrunLogger }), + // logger: dryrunLogger + // }) + + // const assignLogger = logger.child('assign') + // const assign = assignWith({ + // deployAssign: MuClient.deployAssignWith({ + // fetch, + // MU_URL, + // logger: assignLogger + // }), + // logger: messageLogger + // }) + + return { MODE, result, message, spawn, createDataItemSigner: staticWalletDataItemSigner } + } + + /** + * Build the sdk apis using the provided configuration. You can currently specify + * + * - a GATEWAY_URL + * - a GRAPHQL_URL (defaults to GATEWAY_URL/graphql) + * - a GRAPHQL_MAX_RETRIES. Defaults to 0 + * - a GRAPHQL_RETRY_BACKOFF. Defaults to 300 (moot if GRAPHQL_MAX_RETRIES is set to 0) + * - a Messenger Unit URL + * - a Compute Unit URL + * - a AO Unit URL (in mainnet mode) + * - a Relay Unit URL (in relay mode) + * - a wallet to use for signing HTTP messages (in mainnet or relay mode) + * + * If any value is not provided, an SDK default will be used. + * Invoking connect() with no parameters or an empty object is functionally equivalent + * to using the top-lvl exports of the SDK ie. + * + * @example + * import { + * spawn, + * message, + * result, + * results, + * monitor, + * connect + * } from '@permaweb/ao-sdk'; + * + * // These are functionally equivalent + * connect() == { spawn, message, result, results, monitor } + * + * @typedef ConnectArgs + * @property {'legacy' | 'relay' | 'mainnet'} [MODE] - the mode that connect apis will be run in. + * @property {string} [GATEWAY_URL] - the url of the desried Gateway. + * @property {string} [GRAPHQL_URL] - the url of the desired Arweave Gateway GraphQL Server + * @property {number} [GRAPHQL_MAX_RETRIES] - the number of times to retry querying the gateway, utilizing an exponential backoff + * @property {number} [GRAPHQL_RETRY_BACKOFF] - the initial backoff, in milliseconds (moot if GRAPHQL_MAX_RETRIES is set to 0) + * @property {string} [MU_URL] - the url of the desried ao Messenger Unit. Also used as the relay MU in 'relay' mode + * @property {string} [CU_URL] - the url of the desried ao Compute Unit. Also used as the relay CU in 'relay' mode + * @property {string} [AO_URL] - the url of the desried ao Unit. Only applicable in 'mainnet' mode + * @property {string} [RELAY_URL] - the url of the desried relay Unit. Only applicable in 'relay' mode + * @property {any} [wallet] - the wallet used to sign HTTP Messages. Only applicable in 'relay' or 'mainnet' mode + * + * @param {ConnectArgs} [args] + */ + function connect (args = {}) { + let { GRAPHQL_URL, GATEWAY_URL = DEFAULT_GATEWAY_URL, ...restArgs } = args + + if (!GRAPHQL_URL) GRAPHQL_URL = joinUrl({ url: GATEWAY_URL, path: '/graphql' }) + + const MODE = args.MODE || 'legacy' + + if (MODE === 'legacy') return legacyMode({ ...restArgs, GRAPHQL_URL }) + if (MODE === 'relay') return relayMode({ ...restArgs, GRAPHQL_URL }) + if (MODE === 'mainnet') return mainnetMode({ ...restArgs, GRAPHQL_URL }) - return api + throw new Error(`Unrecognized MODE: ${MODE}`) } return connect diff --git a/connect/src/index.js b/connect/src/index.js index b12ae18df..9334535a6 100644 --- a/connect/src/index.js +++ b/connect/src/index.js @@ -1,6 +1,7 @@ import { connectWith, serializeCron } from './index.common.js' import { WalletClient } from './client/node/index.js' + const GATEWAY_URL = process.env.GATEWAY_URL || undefined const MU_URL = process.env.MU_URL || undefined const CU_URL = process.env.CU_URL || undefined @@ -8,25 +9,33 @@ const GRAPHQL_URL = process.env.GRAPHQL_URL || undefined const GRAPHQL_MAX_RETRIES = process.env.GRAPHQL_MAX_RETRIES || undefined const GRAPHQL_RETRY_BACKOFF = process.env.GRAPHQL_RETRY_BACKOFF || undefined -const HB_URL = process.env.HB_URL || undefined +const RELAY_URL = process.env.RELAY_URL || undefined +const AO_URL = process.env.AO_URL = undefined const connect = connectWith({ createDataItemSigner: WalletClient.createDataItemSigner, createHbSigner: WalletClient.createHbSigner }) +/** + * hardcoded to legacy, since wallet is not provided here + * + * TODO: probably remove these at the top level, and require using connect + * so as to set the mode and provide the wallet + */ const { result, results, message, spawn, monitor, unmonitor, dryrun, assign, createDataItemSigner } = connect({ + MODE: 'legacy', GATEWAY_URL, MU_URL, CU_URL, + RELAY_URL, + AO_URL, GRAPHQL_URL, GRAPHQL_MAX_RETRIES, - GRAPHQL_RETRY_BACKOFF + GRAPHQL_RETRY_BACKOFF, + noLog: true }) -const originalHb = connect.hb -connect.hb = ({ URL = HB_URL, ...rest }) => originalHb({ URL, ...rest }) - export { result, results, message, spawn, monitor, unmonitor, dryrun, assign } export { connect } export { serializeCron } diff --git a/connect/src/index.test.js b/connect/src/index.test.js new file mode 100644 index 000000000..91ba47c0d --- /dev/null +++ b/connect/src/index.test.js @@ -0,0 +1,52 @@ +/* eslint-disable no-unused-vars */ +import { describe, test, before, after } from 'node:test' +import * as assert from 'node:assert' +import { tmpdir } from 'node:os' +import { writeFileSync, readFileSync, unlinkSync } from 'node:fs' +import { randomBytes } from 'node:crypto' +import { join } from 'node:path' + +import Arweave from 'arweave' + +import { connect } from './index.js' + +describe('index - node', () => { + /** + * Generate a wallet in a temporary directory prior to running the tests + */ + let tmpWallet + before(async () => { + const arweave = Arweave.init() + + tmpWallet = join(tmpdir(), `${randomBytes(16).toString('hex')}.json`) + writeFileSync( + tmpWallet, + JSON.stringify(await arweave.wallets.generate()) + ) + }) + + after(async () => { + unlinkSync(tmpWallet) + }) + + describe('modes', () => { + test('should return apis in the specified mode', async () => { + const wallet = JSON.parse(readFileSync(tmpWallet).toString()) + + assert.equal( + connect({ MODE: 'legacy' }).MODE, + 'legacy' + ) + + assert.equal( + connect({ MODE: 'relay', wallet }).MODE, + 'relay' + ) + + assert.equal( + connect({ MODE: 'mainnet', wallet }).MODE, + 'mainnet' + ) + }) + }) +})