diff --git a/.github/workflows/deploy-dev-widgets.yml b/.github/workflows/deploy-dev-widgets.yml index 5d0327275..19b6c7379 100644 --- a/.github/workflows/deploy-dev-widgets.yml +++ b/.github/workflows/deploy-dev-widgets.yml @@ -11,5 +11,6 @@ jobs: directory-paths: ${{vars.WIDGETS_DIRECTORY_PATHS}} deploy-account-address: ${{ vars.DEV_SIGNER_ACCOUNT_ID }} signer-public-key: ${{ vars.DEV_SIGNER_PUBLIC_KEY }} + environment: dev secrets: SIGNER_PRIVATE_KEY: ${{ secrets.DEV_SIGNER_PRIVATE_KEY }} diff --git a/.github/workflows/deploy-prod-widgets.yml b/.github/workflows/deploy-prod-widgets.yml index d847626bd..9bdbdcd54 100644 --- a/.github/workflows/deploy-prod-widgets.yml +++ b/.github/workflows/deploy-prod-widgets.yml @@ -11,5 +11,6 @@ jobs: directory-paths: ${{vars.WIDGETS_DIRECTORY_PATHS}} deploy-account-address: ${{ vars.PROD_SIGNER_ACCOUNT_ID }} signer-public-key: ${{ vars.PROD_SIGNER_PUBLIC_KEY }} + environment: mainnet secrets: SIGNER_PRIVATE_KEY: ${{ secrets.PROD_SIGNER_PRIVATE_KEY }} diff --git a/.github/workflows/deploy-widgets.yml b/.github/workflows/deploy-widgets.yml index d57dac082..2ca7f553e 100644 --- a/.github/workflows/deploy-widgets.yml +++ b/.github/workflows/deploy-widgets.yml @@ -1,4 +1,4 @@ -name: Deploy Components to Mainnet +name: Deploy Components on: workflow_call: inputs: @@ -19,6 +19,10 @@ on: required: true description: "Comma-separated paths to the directories that contain the code to be deployed" type: string + environment: + required: true + description: "mainnet or dev" + type: string secrets: SIGNER_PRIVATE_KEY: description: "Private key in `ed25519:` format for signing transaction" @@ -26,17 +30,32 @@ on: jobs: deploy-widgets: runs-on: ubuntu-latest - name: Deploy widgets to social.near (mainnet) + name: Deploy widgets to social.near env: BOS_DEPLOY_ACCOUNT_ID: ${{ inputs.deploy-account-address }} BOS_SIGNER_PUBLIC_KEY: ${{ inputs.signer-public-key }} - BOS_SIGNER_PRIVATE_KEY: ${{ secrets.SIGNER_PRIVATE_KEY }} DIRECTORY_PATHS: ${{ inputs.directory-paths }} + ENVIRONMENT: ${{inputs.environment}} + BOS_SIGNER_PRIVATE_KEY: ${{ secrets.SIGNER_PRIVATE_KEY }} steps: - name: Checkout repository uses: actions/checkout@v2 + - name: Set replacements + id: set_replacements + run: | + cd "frontend/widgets/" + echo "replacements=$(jq -r '[to_entries[] | .["find"] = "${" + .key + "}" | .["replace"] = .value | del(.key, .value)]' ../replacement.${ENVIRONMENT}.json | tr -d "\n\r")" >> $GITHUB_OUTPUT + + - name: Replace placeholders + uses: flcdrg/replace-multiple-action@v1 + with: + files: '**/*.jsx' + find: '${{ steps.set_replacements.outputs.replacements }}' + prefix: '(^|.*)' + suffix: '($|.*)' + - name: Install near-social CLI run: | curl --proto '=https' --tlsv1.2 -LsSf https://github.com/FroVolod/bos-cli-rs/releases/download/v${{ inputs.cli-version }}/bos-cli-v${{ inputs.cli-version }}-installer.sh | sh diff --git a/frontend/README.md b/frontend/README.md index ea5bb0f32..824d47482 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -12,9 +12,11 @@ First, download the bos-loader cli by following this guide [here](https://docs.n From the root of QueryAPI Frontend repo, run the following command ```bash -yarn serve:widgets +yarn serve:widgets:local // for running local enviornment +yarn serve:widgets:dev // for running dev enviornment +yarn serve:widgets:prod // for running prod enviornment ``` -> Near.org or any other BOS gateway queries the blockchain state to pull the latest widgets code and renders it. If we would like to test our BOS widgets, we need to override the path at which the gateway (near.org) queries for the widget code. We do this using the Bos-loader tool (the underlying CLI tool used in the `yarn serve:widgets` command) which allows us to serve out widgets locally (http://127.0.0.1:3030 by default). At this point, we have served our widgets locally but have not yet told the BOS gateway (near.org) where to load our local widgets from. +> Near.org or any other BOS gateway queries the blockchain state to pull the latest widgets code and renders it. If we would like to test our BOS widgets, we need to override the path at which the gateway (near.org) queries for the widget code. We do this using the Bos-loader tool (the underlying CLI tool used in the `yarn serve:widgets:dev` command) which allows us to serve out widgets locally (http://127.0.0.1:3030 by default). ** This command replaces all keys found in `replacement.dev.json` object with the their values in the widgets directory when serving the widgets **. At this point, we have served our widgets locally but have not yet told the BOS gateway (near.org) where to load our local widgets from. **Then, Head to `near.org/flags` and enter `http://127.0.0.1:3030`** @@ -26,26 +28,7 @@ yarn serve:widgets yarn dev ``` - **Now, head to the path where the widgets are served on the BOS.** -- Prod Environment: `https://near.org/dataplatform.near/widget/QueryApi.App` -- Dev Environment: `https://near.org/dev-queryapi.dataplatform.near/widget/QueryApi.dev-App` - ---- -### Notes -> **Make sure to change your widgets code (while testing only) to point to where your local nextJS app is being served.** - -```QueryApi.App.jsx ----const EXTERNAL_APP_URL = "https://queryapi.io"; -+++const EXTERNAL_APP_URL = "http://localhost:3000"; -``` - - -> **You may need to change the accountId argument to the bos-loader CLI command in `package.json` to load from `dataplatform.near` or `dev-queryapi.dataplatform.near`. This depends on what environment you are testing for.** - -`bos-loader dev-queryapi.dataplatform.near --path widgets/src` -`bos-loader dataplatform.near --path widgets/src` - - +- Prod App: `https://near.org/dataplatform.near/widget/QueryApi.App` diff --git a/frontend/package.json b/frontend/package.json index 7a73280e4..ad3b59abf 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -4,7 +4,9 @@ "private": true, "scripts": { "dev": "next dev", - "serve:widgets": "bos-loader dev-queryapi.dataplatform.near --path widgets/src", + "serve:widgets": "bos-loader dataplatform.near --path widgets/src -r replacement.mainnet.json", + "serve:widgets:local": "bos-loader dataplatform.near --path widgets/src -r replacement.local.json", + "serve:widgets:dev": "bos-loader dev-queryapi.dataplatform.near --path widgets/src -r replacement.dev.json", "build": "next build", "start": "next start", "lint": "next lint" diff --git a/frontend/replacement.dev.json b/frontend/replacement.dev.json new file mode 100644 index 000000000..1a233cb9d --- /dev/null +++ b/frontend/replacement.dev.json @@ -0,0 +1,6 @@ +{ + "REPL_ACCOUNT_ID": "dev-queryapi.dataplatform.near", + "REPL_GRAPHQL_ENDPOINT": "https://near-queryapi.dev.api.pagoda.co", + "REPL_EXTERNAL_APP_URL": "https://queryapi-frontend-vcqilefdcq-ew.a.run.app", + "REPL_REGISTRY_CONTRACT_ID": "dev-queryapi.dataplatform.near" +} diff --git a/frontend/replacement.local.json b/frontend/replacement.local.json new file mode 100644 index 000000000..9b8fa584e --- /dev/null +++ b/frontend/replacement.local.json @@ -0,0 +1,6 @@ +{ + "REPL_ACCOUNT_ID": "dataplatform.near", + "REPL_GRAPHQL_ENDPOINT": "https://near-queryapi.api.pagoda.co", + "REPL_EXTERNAL_APP_URL": "http://localhost:3000", + "REPL_REGISTRY_CONTRACT_ID": "queryapi.dataplatform.near" +} diff --git a/frontend/replacement.mainnet.json b/frontend/replacement.mainnet.json new file mode 100644 index 000000000..7a98e12d4 --- /dev/null +++ b/frontend/replacement.mainnet.json @@ -0,0 +1,6 @@ +{ + "REPL_ACCOUNT_ID": "dataplatform.near", + "REPL_GRAPHQL_ENDPOINT": "https://near-queryapi.api.pagoda.co", + "REPL_EXTERNAL_APP_URL": "https://queryapi-frontend-24ktefolwq-ew.a.run.app", + "REPL_REGISTRY_CONTRACT_ID": "queryapi.dataplatform.near" +} diff --git a/frontend/src/components/Playground/graphiql.jsx b/frontend/src/components/Playground/graphiql.jsx index e0aa80f91..672b9200b 100644 --- a/frontend/src/components/Playground/graphiql.jsx +++ b/frontend/src/components/Playground/graphiql.jsx @@ -10,7 +10,7 @@ import '@graphiql/plugin-explorer/dist/style.css'; const HASURA_ENDPOINT = process.env.NEXT_PUBLIC_HASURA_ENDPOINT || - "https://queryapi-hasura-graphql-24ktefolwq-ew.a.run.app/v1/graphql"; + "https://near-queryapi.api.pagoda.co/v1/graphql"; const graphQLFetcher = async (graphQLParams, accountId) => { const response = await fetch(HASURA_ENDPOINT, { diff --git a/frontend/widgets/src/QueryApi.App.jsx b/frontend/widgets/src/QueryApi.App.jsx index b7cbb088c..033ce17bf 100644 --- a/frontend/widgets/src/QueryApi.App.jsx +++ b/frontend/widgets/src/QueryApi.App.jsx @@ -1,8 +1,3 @@ -const GRAPHQL_ENDPOINT = - "https://queryapi-hasura-graphql-24ktefolwq-ew.a.run.app"; -const APP_OWNER = "dataplatform.near"; -const EXTERNAL_APP_URL = "https://queryapi-frontend-24ktefolwq-ew.a.run.app"; -const REGISTRY_CONTRACT_ID = "queryapi.dataplatform.near"; const view = props.view; const path = props.path; const tab = props.tab; @@ -10,12 +5,8 @@ const selectedIndexerPath = props.selectedIndexerPath; return ( { +Near.asyncView(`${REPL_REGISTRY_CONTRACT_ID}`, "list_indexer_functions").then((data) => { const indexers = []; const total_indexers = 0; Object.keys(data.All).forEach((accountId) => { @@ -284,12 +274,13 @@ const ButtonLink = styled.a` }} `; -const previousSelectedTab = Storage.privateGet("queryapi:activeTab"); -if (previousSelectedTab && previousSelectedTab !== state.activeTab) { - State.update({ - activeTab: previousSelectedTab, - }); -} +// TODO fix activeTab +// const previousSelectedTab = Storage.privateGet("queryapi:activeTab"); +// if (previousSelectedTab && previousSelectedTab !== state.activeTab) { +// State.update({ +// activeTab: previousSelectedTab, +// }); +// } const selectTab = (tabName) => { Storage.privateSet("queryapi:activeTab", tabName); @@ -299,10 +290,9 @@ const selectTab = (tabName) => { }; const indexerView = (accountId, indexerName) => { - const editUrl = `https://near.org/#/${APP_OWNER}/widget/QueryApi.${appPath}?selectedIndexerPath=${accountId}/${indexerName}&view=editor-window`; - const statusUrl = `https://near.org/#/${APP_OWNER}/widget/QueryApi.${appPath}?selectedIndexerPath=${accountId}/${indexerName}&view=indexer-status`; - // const playgroundLink = `https://near.org/#/${APP_OWNER}/widget/QueryApi.App?selectedIndexerPath=${accountId}/${indexerName}&view=editor-window&tab=playground`; - const playgroundLink = `https://cloud.hasura.io/public/graphiql?endpoint=${GRAPHQL_ENDPOINT}/v1/graphql&header=x-hasura-role%3A${accountId.replaceAll( + const editUrl = `https://near.org/#/${REPL_ACCOUNT_ID}/widget/QueryApi.App?selectedIndexerPath=${accountId}/${indexerName}&view=editor-window`; + const statusUrl = `https://near.org/#/${REPL_ACCOUNT_ID}/widget/QueryApi.App?selectedIndexerPath=${accountId}/${indexerName}&view=indexer-status`; + const playgroundLink = `https://cloud.hasura.io/public/graphiql?endpoint=${REPL_GRAPHQL_ENDPOINT}/v1/graphql&header=x-hasura-role%3A${accountId.replaceAll( ".", "_" )}`; @@ -357,7 +347,7 @@ return ( > Indexers - {props.view === "create-new-indexer" && ( + {state.activeTab == "create-new-indexer" && ( selectTab("create-new-indexer")} @@ -390,7 +380,7 @@ return (
selectTab("indexers")} > @@ -410,7 +400,7 @@ return (
{ State.update({ @@ -429,13 +419,7 @@ return ( )}
@@ -447,16 +431,12 @@ return ( {state.activeTab === "create-new-indexer" && (
@@ -476,15 +456,11 @@ return ( selected_indexerName ?? state.indexers[0].indexerName )} @@ -504,17 +480,13 @@ return (

{`${state.indexers[0].accountId}/${state.indexers[0].indexerName}`}

))} @@ -528,16 +500,12 @@ return (

{`${state.indexers[0].accountId}/${state.indexers[0].indexerName}`}

))} diff --git a/frontend/widgets/src/QueryApi.Editor.jsx b/frontend/widgets/src/QueryApi.Editor.jsx index 147080a90..8deadca58 100644 --- a/frontend/widgets/src/QueryApi.Editor.jsx +++ b/frontend/widgets/src/QueryApi.Editor.jsx @@ -1,12 +1,7 @@ const path = props.path || "query-api-editor"; const tab = props.tab || ""; -const REGISTRY_CONTRACT_ID = - props.REGISTRY_CONTRACT_ID || "queryapi.dataplatform.near"; let accountId = props.accountId || context.accountId; -let externalAppUrl = - props.EXTERNAL_APP_URL || "https://queryapi-frontend-24ktefolwq-ew.a.run.app"; -externalAppUrl += `/${path}?accountId=${accountId}`; -// let externalAppUrl = `http://localhost:3000/${path}?accountId=${accountId}`; +let externalAppUrl = `${REPL_EXTERNAL_APP_URL}/${path}?accountId=${accountId}`; if (props.indexerName) { externalAppUrl += `&indexerName=${props.indexerName}`; @@ -30,7 +25,7 @@ const registerFunctionHandler = (request, response) => { const jsonFilter = `{"indexer_rule_kind":"Action","matching_rule":{"rule":"ACTION_ANY","affected_account_id":"${contractFilter || "social.near"}","status":"SUCCESS"}}` Near.call( - REGISTRY_CONTRACT_ID, + `${REPL_REGISTRY_CONTRACT_ID}`, "register_indexer_function", { function_name: indexerName, @@ -47,7 +42,7 @@ let deleteIndexer = (request) => { const { indexerName } = request.payload; const gas = 200000000000000; Near.call( - REGISTRY_CONTRACT_ID, + `${REPL_REGISTRY_CONTRACT_ID}`, "remove_indexer_function", { function_name: indexerName, @@ -55,6 +50,7 @@ let deleteIndexer = (request) => { gas ); }; + /** * Request Handlers here */ diff --git a/frontend/widgets/src/QueryApi.IndexerCard.jsx b/frontend/widgets/src/QueryApi.IndexerCard.jsx index 431973dcb..f64545ba3 100644 --- a/frontend/widgets/src/QueryApi.IndexerCard.jsx +++ b/frontend/widgets/src/QueryApi.IndexerCard.jsx @@ -1,14 +1,8 @@ const accountId = props.accountId || context.accountId; const indexerName = props.indexerName; -const GRAPHQL_ENDPOINT = - props.GRAPHQL_ENDPOINT || - "https://queryapi-hasura-graphql-24ktefolwq-ew.a.run.app"; -const APP_OWNER = props.APP_OWNER || "dataplatform.near"; -const appPath = props.appPath || "App"; -const editUrl = `https://near.org/#/${APP_OWNER}/widget/QueryApi.${appPath}?selectedIndexerPath=${accountId}/${indexerName}&view=editor-window`; -const statusUrl = `https://near.org/#/${APP_OWNER}/widget/QueryApi.${appPath}?selectedIndexerPath=${accountId}/${indexerName}&view=indexer-status`; -// const playgroundLink = `https://near.org/#/${APP_OWNER}/widget/QueryApi.App?selectedIndexerPath=${accountId}/${indexerName}&view=editor-window&tab=playground`; -const playgroundLink = `https://cloud.hasura.io/public/graphiql?endpoint=${GRAPHQL_ENDPOINT}/v1/graphql&header=x-hasura-role%3A${accountId.replaceAll( +const editUrl = `https://near.org/#/${REPL_ACCOUNT_ID}/widget/QueryApi.App?selectedIndexerPath=${accountId}/${indexerName}&view=editor-window`; +const statusUrl = `https://near.org/#/${REPL_ACCOUNT_ID}/widget/QueryApi.App?selectedIndexerPath=${accountId}/${indexerName}&view=indexer-status`; +const playgroundLink = `https://cloud.hasura.io/public/graphiql?endpoint=${REPL_GRAPHQL_ENDPOINT}/v1/graphql&header=x-hasura-role%3A${accountId.replaceAll( ".", "_" )}`; diff --git a/frontend/widgets/src/QueryApi.IndexerExplorer.jsx b/frontend/widgets/src/QueryApi.IndexerExplorer.jsx index 62afe4def..8ac6e079e 100644 --- a/frontend/widgets/src/QueryApi.IndexerExplorer.jsx +++ b/frontend/widgets/src/QueryApi.IndexerExplorer.jsx @@ -1,10 +1,4 @@ const limitPerPage = 5; -const REGISTRY_CONTRACT_ID = - props.REGISTRY_CONTRACT_ID || "queryapi.dataplatform.near"; -let APP_OWNER = props.APP_OWNER || "dev-queryapi.dataplatform.near"; -const GRAPHQL_ENDPOINT = - props.GRAPHQL_ENDPOINT || - "https://queryapi-hasura-graphql-24ktefolwq-ew.a.run.app"; let totalIndexers = 0; const accountId = context.accountId; State.init({ @@ -21,7 +15,7 @@ if (props.tab && props.tab !== state.selectedTab) { }); } -Near.asyncView(REGISTRY_CONTRACT_ID, "list_indexer_functions").then((data) => { +Near.asyncView(`${REPL_REGISTRY_CONTRACT_ID}`, "list_indexer_functions").then((data) => { const indexers = []; const total_indexers = 0; Object.keys(data.All).forEach((accountId) => { @@ -242,13 +236,10 @@ return ( {state.all_indexers.map((indexer, i) => ( @@ -275,13 +266,10 @@ return ( {state.my_indexers.map((indexer, i) => ( diff --git a/frontend/widgets/src/QueryApi.IndexerStatus.jsx b/frontend/widgets/src/QueryApi.IndexerStatus.jsx index 492f650e2..4def76129 100644 --- a/frontend/widgets/src/QueryApi.IndexerStatus.jsx +++ b/frontend/widgets/src/QueryApi.IndexerStatus.jsx @@ -1,11 +1,9 @@ //props indexer_name const indexer_name = props.indexer_name; -const GRAPHQL_ENDPOINT = - props.GRAPHQL_ENDPOINT || - "https://queryapi-hasura-graphql-24ktefolwq-ew.a.run.app"; const LIMIT = 20; const accountId = props.accountId || context.accountId; + const H2 = styled.h2` font-size: 19px; line-height: 22px; @@ -110,7 +108,7 @@ State.init({ }); function fetchGraphQL(operationsDoc, operationName, variables) { - return asyncFetch(`${GRAPHQL_ENDPOINT}/v1/graphql`, { + return asyncFetch(`${REPL_GRAPHQL_ENDPOINT}/v1/graphql`, { method: "POST", body: JSON.stringify({ query: operationsDoc, @@ -121,7 +119,7 @@ function fetchGraphQL(operationsDoc, operationName, variables) { } const createGraphQLLink = () => { - const queryLink = `https://cloud.hasura.io/public/graphiql?endpoint=${GRAPHQL_ENDPOINT}/v1/graphql&query=query+IndexerQuery+%7B%0A++indexer_state%28where%3A+%7Bfunction_name%3A+%7B_eq%3A+%22function_placeholder%22%7D%7D%29+%7B%0A++++function_name%0A++++current_block_height%0A++%7D%0A++indexer_log_entries%28%0A++++where%3A+%7Bfunction_name%3A+%7B_eq%3A+%22function_placeholder%22%7D%7D%0A++++order_by%3A+%7B+timestamp%3A+desc%7D%0A++%29+%7B%0A++++function_name%0A++++id%0A++++message%0A++++timestamp%0A++%7D%0A%7D%0A`; + const queryLink = `https://cloud.hasura.io/public/graphiql?endpoint=${REPL_GRAPHQL_ENDPOINT}/v1/graphql&query=query+IndexerQuery+%7B%0A++indexer_state%28where%3A+%7Bfunction_name%3A+%7B_eq%3A+%22function_placeholder%22%7D%7D%29+%7B%0A++++function_name%0A++++current_block_height%0A++%7D%0A++indexer_log_entries%28%0A++++where%3A+%7Bfunction_name%3A+%7B_eq%3A+%22function_placeholder%22%7D%7D%0A++++order_by%3A+%7B+timestamp%3A+desc%7D%0A++%29+%7B%0A++++function_name%0A++++id%0A++++message%0A++++timestamp%0A++%7D%0A%7D%0A`; return queryLink.replaceAll( "function_placeholder", `${accountId}/${indexer_name}` diff --git a/frontend/widgets/src/QueryApi.dev-App.jsx b/frontend/widgets/src/QueryApi.dev-App.jsx deleted file mode 100644 index 224ab9d0d..000000000 --- a/frontend/widgets/src/QueryApi.dev-App.jsx +++ /dev/null @@ -1,25 +0,0 @@ -const GRAPHQL_ENDPOINT = "https://queryapi-hasura-graphql-vcqilefdcq-ew.a.run.app"; -const APP_OWNER = "dev-queryapi.dataplatform.near"; -const EXTERNAL_APP_URL = "https://queryapi-frontend-vcqilefdcq-ew.a.run.app"; -const REGISTRY_CONTRACT_ID = "dev-queryapi.dataplatform.near"; -const view = props.view; -const path = props.path; -const tab = props.tab; -const selectedIndexerPath = props.selectedIndexerPath; - -return ( - -); diff --git a/frontend/widgets/src/QueryApi.dev-App.metadata.json b/frontend/widgets/src/QueryApi.dev-App.metadata.json deleted file mode 100644 index bfbdf4a96..000000000 --- a/frontend/widgets/src/QueryApi.dev-App.metadata.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "description": "Entrypoint to Near QueryAPI's development widget which allows you to seamlessly create, manage, and discover new indexers", - "image": { - }, - "name": "QueryAPI Development", - "tags": { - "development": "" - } -}