Skip to content

Commit

Permalink
Fix in write hooks parser (useScaffoldMultiwriteContracts and useScaf…
Browse files Browse the repository at this point in the history
…foldWriteContracts and useScaffoldReadContracts) add update file contract.ts
  • Loading branch information
Nadai2010 committed Oct 17, 2024
1 parent 0b1e4f9 commit 6877cdd
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 113 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
UseScaffoldWriteConfig,
} from "~~/utils/scaffold-stark/contract";
import { useSendTransaction, useNetwork, Abi } from "@starknet-react/core";
import { InvocationsDetails } from "starknet";
import { Contract as StarknetJsContract, InvocationsDetails } from "starknet";
import { notification } from "~~/utils/scaffold-stark";
import { useMemo } from "react";
import { useTransactor } from "./useTransactor";
Expand Down Expand Up @@ -44,30 +44,38 @@ export const useScaffoldMultiWriteContract = <
contractName as ContractName
] as Contract<TContractName>;

const abiFunction = getFunctionsByStateMutability(
contract?.abi || [],
"external",
).find((fn) => fn.name === functionName);
// TODO: see if we still need this
// const abiFunction = getFunctionsByStateMutability(
// contract?.abi || [],
// "external",
// ).find((fn) => fn.name === functionName);

// we convert to starknetjs contract instance here since deployed data may be undefined if contract is not deployed
const contractInstance = new StarknetJsContract(
contract.abi,
contract.address,
);

return {
contractAddress: contract?.address,
entrypoint: functionName,
calldata:
abiFunction && unParsedArgs && contract
? parseFunctionParams({
abiFunction,
isRead: false,
inputs: unParsedArgs as any[],
isReadArgsParsing: false,
abi: contract.abi,
}).flat()
: [],
...contractInstance.populate(functionName, unParsedArgs as any[]),

// TODO: see if we still need this
// calldata:
// abiFunction && unParsedArgs && contract
// ? parseFunctionParams({
// abiFunction,
// isRead: false,
// inputs: unParsedArgs as any[],
// isReadArgsParsing: false,
// abi: contract.abi,
// }).flat()
// : [],
};
});
} else {
return [];
}
}, [calls]);
}, [calls, targetNetwork.network]);

// TODO add custom options
const sendTransactionInstance = useSendTransaction({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ export const useScaffoldReadContract = <
}) as Omit<ReturnType<typeof useReadContract>, "data"> & {
data: AbiFunctionOutputs<ContractAbi, TFunctionName> | undefined;
};
};
};
173 changes: 93 additions & 80 deletions packages/nextjs/hooks/scaffold-stark/useScaffoldWriteContract.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useMemo } from "react";
import { useCallback, useEffect, useMemo } from "react";
import { useTargetNetwork } from "./useTargetNetwork";
import {
useDeployedContractInfo,
Expand All @@ -12,8 +12,14 @@ import {
parseFunctionParams,
UseScaffoldWriteConfig,
} from "~~/utils/scaffold-stark/contract";
import { useSendTransaction, useNetwork, Abi } from "@starknet-react/core";
import {
useSendTransaction,
useNetwork,
Abi,
useContract,
} from "@starknet-react/core";
import { notification } from "~~/utils/scaffold-stark";
import { Contract as StarknetJsContract } from "starknet";

type UpdatedArgs = Parameters<
ReturnType<typeof useSendTransaction>["sendAsync"]
Expand Down Expand Up @@ -45,93 +51,100 @@ export const useScaffoldWriteContract = <
[deployedContractData?.abi, functionName],
);

const parsedParams = useMemo(() => {
if (args && abiFunction && deployedContractData) {
const parsed = parseFunctionParams({
abiFunction,
abi: deployedContractData.abi,
inputs: args as any[],
isRead: false,
isReadArgsParsing: false,
}).flat(Infinity);
return parsed;
}
return [];
}, [args, abiFunction, deployedContractData]);
// TODO: see if we need this bit later
// const parsedParams = useMemo(() => {
// if (args && abiFunction && deployedContractData) {
// const parsed = parseFunctionParams({
// abiFunction,
// abi: deployedContractData.abi,
// inputs: args as any[],
// isRead: false,
// isReadArgsParsing: true,
// }).flat(Infinity);
// return parsed;
// }
// return [];
// }, [args, abiFunction, deployedContractData]);

const sendTransactionInstance = useSendTransaction({
calls: deployedContractData
? [
{
contractAddress: deployedContractData?.address,
entrypoint: functionName,
calldata: parsedParams,
},
]
: [],
});
// leave blank for now since default args will be called by the trigger function anyway
const sendTransactionInstance = useSendTransaction({});

const sendContractWriteTx = async (params?: {
args?: UseScaffoldWriteConfig<TAbi, TContractName, TFunctionName>["args"];
}) => {
// if no args supplied, use the one supplied from hook
let newArgs = params?.args;
if (Object.keys(newArgs || {}).length <= 0) {
newArgs = args;
}
const sendContractWriteTx = useCallback(
async (params?: {
args?: UseScaffoldWriteConfig<TAbi, TContractName, TFunctionName>["args"];
}) => {
// if no args supplied, use the one supplied from hook
let newArgs = params?.args;
if (Object.keys(newArgs || {}).length <= 0) {
newArgs = args;
}

if (!deployedContractData) {
console.error(
"Target Contract is not deployed, did you forget to run `yarn deploy`?",
if (!deployedContractData) {
console.error(
"Target Contract is not deployed, did you forget to run `yarn deploy`?",
);
return;
}
if (!chain?.id) {
console.error("Please connect your wallet");
return;
}
if (chain?.id !== targetNetwork.id) {
console.error("You are on the wrong network");
return;
}

// TODO: see if we need this back, keeping this here
// let newParsedParams =
// newArgs && abiFunction && deployedContractData
// ? parseFunctionParams({
// abiFunction,
// abi: deployedContractData.abi,
// inputs: newArgs as any[],
// isRead: false,
// isReadArgsParsing: false,
// })
// : parsedParams;

// we convert to starknetjs contract instance here since deployed data may be undefined if contract is not deployed
const contractInstance = new StarknetJsContract(
deployedContractData.abi,
deployedContractData.address,
);
return;
}
if (!chain?.id) {
console.error("Please connect your wallet");
return;
}
if (chain?.id !== targetNetwork.id) {
console.error("You are on the wrong network");
return;
}

let newParsedParams =
newArgs && abiFunction && deployedContractData
? parseFunctionParams({
abiFunction,
abi: deployedContractData.abi,
inputs: newArgs as any[],
isRead: false,
isReadArgsParsing: false,
}).flat(Infinity)
: parsedParams;
const newCalls = [
{
contractAddress: deployedContractData.address,
entrypoint: functionName,
calldata: newParsedParams,
},
];
const newCalls = deployedContractData
? [contractInstance.populate(functionName, newArgs as any[])]
: [];

if (sendTransactionInstance.sendAsync) {
try {
// setIsMining(true);
return await sendTxnWrapper(() =>
sendTransactionInstance.sendAsync(newCalls as any[]),
);
} catch (e: any) {
throw e;
} finally {
// setIsMining(false);
if (sendTransactionInstance.sendAsync) {
try {
// setIsMining(true);
return await sendTxnWrapper(() =>
sendTransactionInstance.sendAsync(newCalls as any[]),
);
} catch (e: any) {
throw e;
} finally {
// setIsMining(false);
}
} else {
notification.error("Contract writer error. Try again.");
return;
}
} else {
notification.error("Contract writer error. Try again.");
return;
}
};
},
[
args,
chain?.id,
deployedContractData,
functionName,
sendTransactionInstance,
sendTxnWrapper,
targetNetwork.id,
],
);

return {
...sendTransactionInstance,
sendAsync: sendContractWriteTx,
};
};
};
48 changes: 34 additions & 14 deletions packages/nextjs/utils/scaffold-stark/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,22 +239,16 @@ export type ExtractAbiFunctionNamesScaffold<
TAbiStateMutability extends AbiStateMutability = AbiStateMutability,
> = ExtractAbiFunctionsScaffold<TAbi, TAbiStateMutability>["name"];

// helper function will only take from interfaces : //TODO: see if we can make it more generic
// helper function will only take from interfaces : //TODO: see if we can make it more generic
export type ExtractAbiFunctionsScaffold<
TAbi extends Abi,
TAbiStateMutability extends AbiStateMutability = AbiStateMutability,
> = Extract<
ExtractAbiInterfaces<TAbi>["items"][number],
| {
state_mutability: TAbiStateMutability;
}
| Extract<
TAbi[number],
{
type: "function";
}
>
{
type: "function";
state_mutability: TAbiStateMutability;
}
>;

// helper function will only take from interfaces : //TODO: see if we can make it more generic
Expand Down Expand Up @@ -334,6 +328,31 @@ export type AbiFunctionOutputs<
TFunctionName extends string,
> = ExtractAbiFunctionScaffold<TAbi, TFunctionName>["outputs"];

/*export type AbiEventInputs<TAbi extends Abi, TEventName extends ExtractAbiEventNames<TAbi>> = ExtractAbiEvent<
TAbi,
TEventName
>["inputs"];
type IndexedEventInputs<
TContractName extends ContractName,
TEventName extends ExtractAbiEventNames<ContractAbi<TContractName>>,
> = Extract<AbiEventInputs<ContractAbi<TContractName>, TEventName>[number], { indexed: true }>;
export type EventFilters<
TContractName extends ContractName,
TEventName extends ExtractAbiEventNames<ContractAbi<TContractName>>,
> = IsContractDeclarationMissing<
any,
IndexedEventInputs<TContractName, TEventName> extends never
? never
: {
[Key in IsContractDeclarationMissing<
any,
IndexedEventInputs<TContractName, TEventName>["name"]
>]?: AbiParameterToPrimitiveType<Extract<IndexedEventInputs<TContractName, TEventName>, { name: Key }>>;
}
>;*/

export type UseScaffoldEventHistoryConfig<
TContractName extends ContractName,
TEventName extends ExtractAbiEventNames<ContractAbi<TContractName>>,
Expand Down Expand Up @@ -764,13 +783,11 @@ export function parseFunctionParams({
args: inputs,
});

console.debug({ formattedInputs });

formattedInputs.forEach((inputItem) => {
const { type: inputType, value: inputValue } = inputItem;

parsedInputs.push(
parseParamWithType(inputType, inputValue, isRead, !!isReadArgsParsing),
deepParseValues(inputValue, isRead, inputType, !!isReadArgsParsing),
);
});

Expand Down Expand Up @@ -822,7 +839,10 @@ function formatInputForParsing({
_formatInput(structValue, argIndex, variants as AbiParameter[]),
];
});
return { type: structName, value: { variant: Object.fromEntries } };
return {
type: structName,
value: { variant: Object.fromEntries(formattedEntries) },
};
}

const { members } = structDef as AbiStruct;
Expand Down

0 comments on commit 6877cdd

Please sign in to comment.