diff --git a/frontend/src/components/Editor/Editor.jsx b/frontend/src/components/Editor/Editor.jsx index 55f62b43b..3d6fc23cd 100644 --- a/frontend/src/components/Editor/Editor.jsx +++ b/frontend/src/components/Editor/Editor.jsx @@ -250,11 +250,22 @@ const Editor = ({ actionButtonText }) => { return; } + let startBlock = null; + if (indexerConfig.startBlock === "startBlockHeight") { + startBlock = { + HEIGHT: indexerConfig.height + }; + } else if (indexerConfig.startBlock === "startBlockLatest") { + startBlock = "LATEST"; + } else { + startBlock = "CONTINUE" + } + request("register-function", { indexerName: indexerName, code: innerCode, schema: validatedSchema, - blockHeight: indexerConfig.startBlockHeight, + startBlock, contractFilter: indexerConfig.filter, }); diff --git a/frontend/src/components/Editor/EditorButtons.jsx b/frontend/src/components/Editor/EditorButtons.jsx index 335466c47..a6a1de9b7 100644 --- a/frontend/src/components/Editor/EditorButtons.jsx +++ b/frontend/src/components/Editor/EditorButtons.jsx @@ -83,7 +83,7 @@ const EditorButtons = ({ Contract Filter { const { indexerDetails, showPublishModal, isCreateNewIndexer, latestHeight } = useContext(IndexerDetailsContext); const [blockHeight, setBlockHeight] = useState("0"); const [contractFilter, setContractFilter] = useState("social.near"); - const [selectedOption, setSelectedOption] = useState("latestBlockHeight"); + const [startBlock, setStartBlock] = useState(START_BLOCK.LATEST); const [isContractFilterValid, setIsContractFilterValid] = useState(true); const [indexerNameField, setIndexerNameField] = useState(indexerDetails.indexerName || ""); const [blockHeightError, setBlockHeightError] = useState(null) - const handleOptionChange = (event) => { - setSelectedOption(event.target.value); - // setBlockHeightError(null); - }; - useEffect(() => { - if (indexerDetails.config?.startBlockHeight) { - setSelectedOption("specificBlockHeight") - setBlockHeight(indexerDetails.config.startBlockHeight) + if (indexerDetails.rule?.affected_account_id) { + setContractFilter(indexerDetails.rule.affected_account_id) } - if (indexerDetails.config?.filter) { - setContractFilter(indexerDetails.config.filter) + + if (indexerDetails.startBlock?.HEIGHT) { + setStartBlock(START_BLOCK.HEIGHT) + setBlockHeight(indexerDetails.startBlock.HEIGHT) + return; + } + + if (indexerDetails.startBlock == "LATEST") { + setStartBlock(START_BLOCK.LATEST) + return; + } + + if (indexerDetails.startBlock == "CONTINUE") { + setStartBlock(START_BLOCK.CONTINUE) + return; } }, [indexerDetails]) - function handleSetContractFilter(e) { - const contractFilter = e.target.value; + const onChangeStartBlock = (e) => { + setStartBlock(e.target.value) + + if (e.target.value === START_BLOCK.CONTINUE) { + handleSetContractFilter(indexerDetails.rule.affected_account_id) + } + } + + function handleSetContractFilter(contractFilter) { setContractFilter(contractFilter); const isContractFilterValid = validateContractIds(contractFilter); setIsContractFilterValid(isContractFilterValid); } useEffect(() => { - if (selectedOption == "specificBlockHeight" && blockHeight <= GENESIS_BLOCK_HEIGHT) { - setBlockHeightError(() => `Choose a block height greater than the Genesis BlockHeight ${GENESIS_BLOCK_HEIGHT}. Latest Block Height is ${latestHeight}`) - return - } - setBlockHeightError(() => null) - updateConfig(indexerNameField, contractFilter, blockHeight, selectedOption) - }, - [indexerNameField, contractFilter, selectedOption, blockHeight]) + if (startBlock == START_BLOCK.HEIGHT && blockHeight <= GENESIS_BLOCK_HEIGHT) { + setBlockHeightError(() => `Choose a block height greater than the Genesis BlockHeight ${GENESIS_BLOCK_HEIGHT}. Latest Block Height is ${latestHeight}`) + return + } + setBlockHeightError(() => null) + updateConfig(indexerNameField, contractFilter, blockHeight, startBlock) + }, + [indexerNameField, contractFilter, startBlock, blockHeight] + ) return ( <> @@ -58,23 +82,34 @@ const IndexerConfigOptions = ({ updateConfig }) => { onChange={(e) => setIndexerNameField(e.target.value.toLowerCase().trim())} /> + + + Start from latest block + + {!isCreateNewIndexer && ( - From Latest Block Height + Continue from last processed block - + )} + - Specific Block Height + Start from block height setBlockHeight(parseInt(e.target.value))} @@ -86,19 +121,25 @@ const IndexerConfigOptions = ({ updateConfig }) => { )} - - Contract Filter + + Contract Filter handleSetContractFilter(e.target.value)} isValid={isContractFilterValid} type="text" placeholder="social.near" required={true} + disabled={startBlock === START_BLOCK.CONTINUE} /> Please provide a valid contract name. + {startBlock === START_BLOCK.CONTINUE && ( + + Contract filter cannot be changed for "Continue" option. + + )} ); diff --git a/frontend/src/components/Logs/LogButtons.jsx b/frontend/src/components/Logs/LogButtons.jsx index cab283b36..49963a8b8 100644 --- a/frontend/src/components/Logs/LogButtons.jsx +++ b/frontend/src/components/Logs/LogButtons.jsx @@ -78,7 +78,7 @@ const LogButtons = ({ Contract Filter { - if (option === "latestBlockHeight") { - startBlockHeight = null - } - setIndexerConfig({ filter, startBlockHeight }) + const updateConfig = (indexerName, filter, height, startBlock) => { + setIndexerConfig({ filter, startBlock, height }) setIndexerName(indexerName) } diff --git a/frontend/src/contexts/IndexerDetailsContext.js b/frontend/src/contexts/IndexerDetailsContext.js index 29ab66ecc..bce401961 100644 --- a/frontend/src/contexts/IndexerDetailsContext.js +++ b/frontend/src/contexts/IndexerDetailsContext.js @@ -22,7 +22,7 @@ import { getLatestBlockHeight } from "../utils/getLatestBlockHeight"; // } export const IndexerDetailsContext = React.createContext({ - indexerDetails: { code: undefined, schema: undefined, config: { filter: "social.near", startBlockHeight: null }, accountId: "", indexerName: "" }, + indexerDetails: { code: undefined, schema: undefined, rule: { affected_account_id: "social.near" }, startBlock: "LATEST", accountId: "", indexerName: "" }, showResetCodeModel: false, setShowResetCodeModel: () => { }, showPublishModal: false, @@ -47,7 +47,7 @@ export const IndexerDetailsContext = React.createContext({ export const IndexerDetailsProvider = ({ children }) => { const [accountId, setAccountId] = useState(undefined); const [indexerName, setIndexerName] = useState(undefined); - const [indexerDetails, setIndexerDetails] = useState({ code: undefined, schema: undefined, config: { filter: "social.near", startBlockHeight: null }, accountId: accountId, indexerName: indexerName }) + const [indexerDetails, setIndexerDetails] = useState({ code: undefined, schema: undefined, rule: { affected_account_id: "social.near" }, startBlock: "LATEST", accountId: accountId, indexerName: indexerName }) const [showResetCodeModel, setShowResetCodeModel] = useState(false); const [showPublishModal, setShowPublishModal] = useState(false); const [showForkIndexerModal, setShowForkIndexerModal] = useState(false); @@ -65,16 +65,13 @@ export const IndexerDetailsProvider = ({ children }) => { const requestIndexerDetails = async () => { const data = await queryIndexerFunctionDetails(accountId, indexerName); if (data) { - const indexerConfig = { - startBlockHeight: data.start_block_height, - filter: data.filter.matching_rule.affected_account_id, - } const details = { accountId: accountId, indexerName: indexerName, code: wrapCode(data.code), schema: data.schema, - config: indexerConfig + startBlock: data.start_block, + rule: data.rule } return details } @@ -102,7 +99,8 @@ export const IndexerDetailsProvider = ({ children }) => { indexerName: indexer.indexerName, code: indexer.code, schema: indexer.schema, - config: indexer.config + startBlock: indexer.startBlock, + rule: indexer.rule } setIndexerDetails(details); })(); diff --git a/frontend/src/utils/queryIndexerFunction.js b/frontend/src/utils/queryIndexerFunction.js index 06ee177e7..70ea7b20f 100644 --- a/frontend/src/utils/queryIndexerFunction.js +++ b/frontend/src/utils/queryIndexerFunction.js @@ -8,21 +8,27 @@ const provider = new providers.JsonRpcProvider( ); export const queryIndexerFunctionDetails = async (accountId, functionName) => { - let args = { account_id: accountId, function_name: functionName }; + let args = { account_id: accountId }; try { const result = await provider.query({ request_type: "call_function", account_id: REGISTRY_CONTRACT, - method_name: "read_indexer_function", + // TODO Create method to query single indexer + method_name: "list_by_account", args_base64: Buffer.from(JSON.stringify(args)).toString("base64"), finality: "optimistic", }); - return ( - result.result && + + const indexers = result.result && result.result.length > 0 && - JSON.parse(Buffer.from(result.result).toString()) - ); + JSON.parse(Buffer.from(result.result).toString()); + + if (!indexers) { + return null; + } + + return indexers[functionName]; } catch (error) { console.log(`Could not query indexer function details from registry ${REGISTRY_CONTRACT}, for ${accountId}/${functionName}`) console.log(error, "error"); diff --git a/frontend/widgets/src/QueryApi.Dashboard.jsx b/frontend/widgets/src/QueryApi.Dashboard.jsx index 2771a3f62..6fff8d4a2 100644 --- a/frontend/widgets/src/QueryApi.Dashboard.jsx +++ b/frontend/widgets/src/QueryApi.Dashboard.jsx @@ -17,11 +17,11 @@ State.init({ selected_account: undefined, }); -Near.asyncView(`${REPL_REGISTRY_CONTRACT_ID}`, "list_indexer_functions").then((data) => { +Near.asyncView(`${REPL_REGISTRY_CONTRACT_ID}`, "list_all").then((data) => { const indexers = []; const total_indexers = 0; - Object.keys(data.All).forEach((accountId) => { - Object.keys(data.All[accountId]).forEach((functionName) => { + Object.keys(data).forEach((accountId) => { + Object.keys(data[accountId]).forEach((functionName) => { indexers.push({ accountId: accountId, indexerName: functionName, diff --git a/frontend/widgets/src/QueryApi.Editor.jsx b/frontend/widgets/src/QueryApi.Editor.jsx index 8e37a34f6..e7ab3f47c 100644 --- a/frontend/widgets/src/QueryApi.Editor.jsx +++ b/frontend/widgets/src/QueryApi.Editor.jsx @@ -18,20 +18,24 @@ const initialPayload = { const registerFunctionHandler = (request, response) => { const gas = 200000000000000; - const { indexerName, code, schema, blockHeight, contractFilter } = + const { indexerName, code, schema, startBlock, contractFilter } = request.payload; const jsonFilter = `{"indexer_rule_kind":"Action","matching_rule":{"rule":"ACTION_ANY","affected_account_id":"${contractFilter || "social.near"}","status":"SUCCESS"}}` Near.call( `${REPL_REGISTRY_CONTRACT_ID}`, - "register_indexer_function", + "register", { function_name: indexerName, code, schema, - start_block_height: blockHeight, - filter_json: jsonFilter + start_block: startBlock, + rule: { + kind: "ACTION_ANY", + affected_account_id: contractFilter, + status: "SUCCESS" + } }, gas ); diff --git a/frontend/widgets/src/QueryApi.IndexerExplorer.jsx b/frontend/widgets/src/QueryApi.IndexerExplorer.jsx index 8ac6e079e..8f4e0529f 100644 --- a/frontend/widgets/src/QueryApi.IndexerExplorer.jsx +++ b/frontend/widgets/src/QueryApi.IndexerExplorer.jsx @@ -15,11 +15,11 @@ if (props.tab && props.tab !== state.selectedTab) { }); } -Near.asyncView(`${REPL_REGISTRY_CONTRACT_ID}`, "list_indexer_functions").then((data) => { +Near.asyncView(`${REPL_REGISTRY_CONTRACT_ID}`, "list_all").then((data) => { const indexers = []; const total_indexers = 0; - Object.keys(data.All).forEach((accountId) => { - Object.keys(data.All[accountId]).forEach((functionName) => { + Object.keys(data).forEach((accountId) => { + Object.keys(data[accountId]).forEach((functionName) => { indexers.push({ accountId: accountId, indexerName: functionName,