Skip to content

Instantly share code, notes, and snippets.

@tomusdrw
Created June 2, 2021 14:16
Show Gist options
  • Save tomusdrw/6be7adb067ba44920931d8146f7467f7 to your computer and use it in GitHub Desktop.
Save tomusdrw/6be7adb067ba44920931d8146f7467f7 to your computer and use it in GitHub Desktop.
type PayloadType = {
};
type EstimateFeeType = {};
class ApiCalls {
async estimateFee(chain: Chain, laneId: LaneId, payload: PayloadType): EstimateFeeType {
const payloadType = createType(chain, "OutboundPayload", payload);
return await stateCall(estimateFeeMethod, ...);
}
}
function Component() {
const apiCalls: ApiCalls = useApiCalls();
const { isFeeCalculating, setFeeCalculating} = useState(false);
const { fee, setFee } = useState(null);
const { feeError, setFeeError } = useState(null);
useEffect(() => {
setFeeCalculating(true);
setFee(null);
try {
const fee = await apiCalls.estimateFee(chain, laneId, payload)
setFee(fee);
setFeeCalculating(false);
} catch (e) {
setFeeCalculating(false);
setFeeError("error");
}
});
}
import {useEstimateFee} from './hooks/api/useEstimateFee';
function Component() {
const { fee: number | null, feeError: string|null, isFeeCalculating: bool, recalculateFee: () => void } = useEstimateFee(laneId, ...);
fee==null
isFeeCalculating == true
//
useEffect(() => {
recalculateFee();
});
}
@hbulgarini
Copy link

I was diving a little more on this and trying to bring all what we discuss to our existing processes. And here my conclusions:

  1. store.js : is exactly what we have now, but split in different reducers per concern. I would not join them all in one global reducer since one update on each specific concern would force all the reducers to update.

  2. useApi.ts: I think there should be two separate hooks, the useApi.ts as it is in your example code nikos, but then the generic call should be extracted to a different process.

  3. useGenericCall.ts: i think this is a pretty useful and reusable hook but it was pretty hard to add the logic to handle global calls which are provided to it as input props of the hook. The main problem i faced with this is that when you have to provide the global functions as input props for this hook , it is really easy to forget a useCallback that will make the whole app to enter in a rerender infinite loop.
    So my recommendation is to keep this generic call hook, but to only use it when this hook is going to be used locally ( without having to use this values as global)

  4. Global calls: My preferred options is to use reducers. Not only for the benefits of state management flow , etc, but also because i have confirmed that the use of the dispatcher is much much more secure in terms of rerender control than sharing trough props chains or context a wrapped function that will end calling a setState. In case those calls are not properly wrapped in a useCallback everything gets rerender again because the function reference is different in each render.

So my suggested rule is in case a value has to be global ( as estimatedFee and payload ) , they should have their own dedicated hook that will expose a function that will handle their corresponding update status with dispatchers ( similar to my first comment )

@wirednkod
Copy link

wirednkod commented Jun 11, 2021

The following can really make all the above TLDR and show what I mean in idea.ts and project I built.
I am approaching it more like this:

  • Layer 1: API Layer ----------------------> PolkadotJS API
  • Layer 2: Bridges API specific Layer -----> Bridges API that uses specific needed things from polkadotJS API (not all API calls from polkadot JS are needed
  • Layer 3: Bridges Simple/Specific Business logic ----------> Functions/hooks that are using the Bridges API for 1 VERY specific reusable action (get the chain, estimate fee etc etc)
  • Layer 4: Bridges Advanced/Complicated Logic ---------> Functions/hooks that can use any of Layers 2, 3 to make complicated logic (send a transaction and estimate fee and do something else at the same time)
  • Layer 5: Bridges or other Bridges-related UI ------> UI components that can use any of Layers 2 - 4, to re-create or reuse Bridges functionalities (simple or complicated)

Layers 2 -4 is the "library" we need to build. Layer 5 should be the actual Bridges UI. Layer 2-4 should ALWAYS work with specific version of Layer 1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment