Skip to content

Commit

Permalink
feat: add replacement map feature (#176)
Browse files Browse the repository at this point in the history
  • Loading branch information
roshaans committed Aug 16, 2023
1 parent 444fba3 commit 73f8786
Show file tree
Hide file tree
Showing 17 changed files with 85 additions and 160 deletions.
1 change: 1 addition & 0 deletions .github/workflows/deploy-dev-widgets.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }}
1 change: 1 addition & 0 deletions .github/workflows/deploy-prod-widgets.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }}
25 changes: 22 additions & 3 deletions .github/workflows/deploy-widgets.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Deploy Components to Mainnet
name: Deploy Components
on:
workflow_call:
inputs:
Expand All @@ -19,24 +19,43 @@ 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:<private_key>` format for signing transaction"
required: true
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
Expand Down
27 changes: 5 additions & 22 deletions frontend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`**
Expand All @@ -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`

4 changes: 3 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
6 changes: 6 additions & 0 deletions frontend/replacement.dev.json
Original file line number Diff line number Diff line change
@@ -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"
}
6 changes: 6 additions & 0 deletions frontend/replacement.local.json
Original file line number Diff line number Diff line change
@@ -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"
}
6 changes: 6 additions & 0 deletions frontend/replacement.mainnet.json
Original file line number Diff line number Diff line change
@@ -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"
}
2 changes: 1 addition & 1 deletion frontend/src/components/Playground/graphiql.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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, {
Expand Down
11 changes: 1 addition & 10 deletions frontend/widgets/src/QueryApi.App.jsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,12 @@
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;
const selectedIndexerPath = props.selectedIndexerPath;

return (
<Widget
src={`${APP_OWNER}/widget/QueryApi.Dashboard`}
src={`${REPL_ACCOUNT_ID}/widget/QueryApi.Dashboard`}
props={{
GRAPHQL_ENDPOINT,
APP_OWNER,
EXTERNAL_APP_URL,
REGISTRY_CONTRACT_ID,
view,
path,
tab,
Expand Down
72 changes: 20 additions & 52 deletions frontend/widgets/src/QueryApi.Dashboard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,16 @@ const [selected_accountId, selected_indexerName] = props.selectedIndexerPath
const activeTab = props.view ?? "indexers";
const limit = 7;
let totalIndexers = 0;
const REGISTRY_CONTRACT_ID =
props.REGISTRY_CONTRACT_ID || "queryapi.dataplatform.near";
const APP_OWNER = props.APP_OWNER || "dataplatform.near";
const GRAPHQL_ENDPOINT =
props.GRAPHQL_ENDPOINT ||
"https://queryapi-hasura-graphql-24ktefolwq-ew.a.run.app";
const EXTERNAL_APP_URL =
props.EXTERNAL_APP_URL || "https://queryapi-frontend-24ktefolwq-ew.a.run.app";

let appPath = props.isDev ? "dev-App" : "App";

State.init({
activeTab: Storage.privateGet("queryapi:activeTab") || activeTab,
activeTab: activeTab,
my_indexers: [],
all_indexers: [],
selected_indexer: undefined,
selected_account: undefined,
});

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) => {
Expand Down Expand Up @@ -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);
Expand All @@ -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(
".",
"_"
)}`;
Expand Down Expand Up @@ -357,7 +347,7 @@ return (
>
Indexers
</TabsButton>
{props.view === "create-new-indexer" && (
{state.activeTab == "create-new-indexer" && (
<TabsButton
type="button"
onClick={() => selectTab("create-new-indexer")}
Expand Down Expand Up @@ -390,7 +380,7 @@ return (
<Main>
<Section active={state.activeTab === "indexers"}>
<NavBarLogo
href={`https://near.org/#/${APP_OWNER}/widget/QueryApi.${appPath}`}
href={`https://near.org/#/${REPL_ACCOUNT_ID}/widget/QueryApi.App`}
title="QueryApi"
onClick={() => selectTab("indexers")}
>
Expand All @@ -410,7 +400,7 @@ return (

<div>
<ButtonLink
href={`/#/${APP_OWNER}/widget/QueryApi.${appPath}/?view=create-new-indexer`}
href={`/#/${REPL_ACCOUNT_ID}/widget/QueryApi.App/?view=create-new-indexer`}
style={{ "margin-top": "10px" }}
onClick={() => {
State.update({
Expand All @@ -429,13 +419,7 @@ return (
</H2>
)}
<Widget
src={`${APP_OWNER}/widget/QueryApi.IndexerExplorer`}
props={{
GRAPHQL_ENDPOINT,
REGISTRY_CONTRACT_ID,
APP_OWNER,
appPath,
}}
src={`${REPL_ACCOUNT_ID}/widget/QueryApi.IndexerExplorer`}
/>
</div>
</Section>
Expand All @@ -447,16 +431,12 @@ return (
{state.activeTab === "create-new-indexer" && (
<div>
<Widget
src={`${APP_OWNER}/widget/QueryApi.Editor`}
src={`${REPL_ACCOUNT_ID}/widget/QueryApi.Editor`}
props={{
indexerName:
selected_indexerName ?? state.indexers[0].indexerName,
accountId: selected_accountId ?? state.indexers[0].accountId,
path: "create-new-indexer",
EXTERNAL_APP_URL,
REGISTRY_CONTRACT_ID,
GRAPHQL_ENDPOINT,
APP_OWNER,
}}
/>
</div>
Expand All @@ -476,15 +456,11 @@ return (
selected_indexerName ?? state.indexers[0].indexerName
)}
<Widget
src={`${APP_OWNER}/widget/QueryApi.IndexerStatus`}
src={`${REPL_ACCOUNT_ID}/widget/QueryApi.IndexerStatus`}
props={{
indexer_name:
selected_indexerName ?? state.indexers[0].indexerName,
accountId: selected_accountId ?? state.indexers[0].accountId,
EXTERNAL_APP_URL,
REGISTRY_CONTRACT_ID,
GRAPHQL_ENDPOINT,
APP_OWNER,
}}
/>
</div>
Expand All @@ -504,17 +480,13 @@ return (
<H2>{`${state.indexers[0].accountId}/${state.indexers[0].indexerName}`}</H2>
))}
<Widget
src={`${APP_OWNER}/widget/QueryApi.Editor`}
src={`${REPL_ACCOUNT_ID}/widget/QueryApi.Editor`}
props={{
indexerName:
selected_indexerName ?? state.indexers[0].indexerName,
accountId: selected_accountId ?? state.indexers[0].accountId,
path: "query-api-editor",
tab: props.tab,
EXTERNAL_APP_URL,
REGISTRY_CONTRACT_ID,
GRAPHQL_ENDPOINT,
APP_OWNER,
}}
/>
</div>
Expand All @@ -528,16 +500,12 @@ return (
<H2>{`${state.indexers[0].accountId}/${state.indexers[0].indexerName}`}</H2>
))}
<Widget
src={`${APP_OWNER}/widget/QueryApi.Editor`}
src={`${REPL_ACCOUNT_ID}/widget/QueryApi.Editor`}
props={{
indexerName:
selected_indexerName ?? state.indexers[0].indexerName,
accountId: selected_accountId ?? state.indexers[0].accountId,
path: "create-new-indexer",
EXTERNAL_APP_URL,
REGISTRY_CONTRACT_ID,
GRAPHQL_ENDPOINT,
APP_OWNER,
}}
/>
</div>
Expand Down
12 changes: 4 additions & 8 deletions frontend/widgets/src/QueryApi.Editor.jsx
Original file line number Diff line number Diff line change
@@ -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}`;
Expand All @@ -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,
Expand All @@ -47,14 +42,15 @@ 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,
},
gas
);
};

/**
* Request Handlers here
*/
Expand Down
Loading

0 comments on commit 73f8786

Please sign in to comment.