diff --git a/components/NewSubgraph/NewSubgraph.tsx b/components/NewSubgraph/NewSubgraph.tsx index dcd9b14..f7e443d 100644 --- a/components/NewSubgraph/NewSubgraph.tsx +++ b/components/NewSubgraph/NewSubgraph.tsx @@ -86,20 +86,21 @@ const ButtonsContainer = styled.div` } ` -export type ExtendedContract = Contract & { errorMessage?: string } - const ADDRESS_REGEX = /^0x[0-9a-f]{40}$/i +const MAPPING_FILENAME = 'mapping.ts' +export type ExtendedContract = Contract & { errorMessage?: string } export const NewSubgraph = () => { const CHAIN_ID = '1' const [subgraphId, setSubgraphId] = useEditorState('subgraph-file') - const { subgraph, saveContracts } = useLocalSubgraph(subgraphId) + const { subgraph, saveContracts, saveMapping } = useLocalSubgraph(subgraphId) const [contractAddress, setContractAddress] = useState('') const [started, setStarted] = useState(false) const [selectedContracts, setSelectedContracts] = useState( subgraph?.contracts || [] ) + const [mappingFunctionNames, setMappingFunctionNames] = useState([]) const router = useRouter() const [fnExtractionLoading, setFnExtractionLoading] = useState(false) @@ -144,6 +145,12 @@ export const NewSubgraph = () => { } }, [subgraph?.mappings[DEFAULT_MAPPING]]) + useEffect(() => { + if (subgraph?.contracts && !selectedContracts.length) { + setSelectedContracts(subgraph.contracts) + } + }, [subgraph]) + useEffect(() => { setStarted(true) }, []) @@ -168,10 +175,28 @@ export const NewSubgraph = () => { const save = () => { let id = subgraphId + const newFnsToInsert: string[] = [] + const contractsToSave = selectedContracts.map(sc => ({ + ...sc, + events: sc.events.map((sce, i) => { + if (sce.handler === 'newFunction') { + const newFnName = `handle${sce.signature.split('(')[0]}${i}` + newFnsToInsert.push(`\nexport function ${newFnName}():void {}\n`) + return { ...sce, handler: newFnName } + } + + return sce + }), + })) + if (subgraph) { - saveContracts(selectedContracts) + saveMapping( + MAPPING_FILENAME, + subgraph.mappings[MAPPING_FILENAME].concat(newFnsToInsert.join('m')) + ) + saveContracts(contractsToSave) } else { - id = newSubgraph({ contracts: selectedContracts }) + id = newSubgraph({ contracts: contractsToSave }) } setSubgraphId(id) router.push('/editor/subgraph') diff --git a/components/NewSubgraph/SelectedContract.tsx b/components/NewSubgraph/SelectedContract.tsx index 156c182..4e01dea 100644 --- a/components/NewSubgraph/SelectedContract.tsx +++ b/components/NewSubgraph/SelectedContract.tsx @@ -114,7 +114,7 @@ function parseEventsFromAbi(abi: any[]) { .map( e => `${e.name}(${e.inputs - .map((ei: any) => `${ei.indexed ? 'indexed ' : ''}${ei.type}`) + .map((ei: any) => `${ei.indexed ? 'indexed ' : ''}${ei.type} ${ei.name}`) .join(', ')})` ) } @@ -135,11 +135,16 @@ export const SelectedContract = (props: SelectedContractProps) => { label: efa, value: efa, })) - const mappingFunctionsSelectOptions = mappingFunctionNames.map(mfn => ({ - label: mfn, - value: mfn, - })) - const [eventHandlers, setEventHandlers] = useState([{ signature: '', handler: '' }]) + const mappingFunctionsSelectOptions = [ + { label: 'Create new handler', value: 'newFunction' }, + ...mappingFunctionNames.map(mfn => ({ + label: mfn, + value: mfn, + })), + ] + const [eventHandlers, setEventHandlers] = useState([ + { signature: '', handler: 'newFunction' }, + ]) const fetchMetadata = async () => { const metadataReq = await fetch(`/api/etherscan/${addresses[CHAIN_ID]}/metadata`) @@ -284,7 +289,9 @@ export const SelectedContract = (props: SelectedContractProps) => { fullWidth={false} variant="outline" className="new-event-handler-btn" - onClick={() => setEventHandlers(prev => [...prev, { signature: '', handler: '' }])} + onClick={() => + setEventHandlers(prev => [...prev, { signature: '', handler: 'newFunction' }]) + } {...(!contractHasEvents && { disabled: true, title: 'Contract has no events defined' })}> Add new event handler