Contract Call Sync
Web3-Redux offers enhanced customizability of contract call syncing to avoid unecessary rpc calls. Contract call syncing is achieved by refreshing contract calls based on a set of parameters.
Simple Contract Call
TODO
Generic Sync
This type union of Sync.
- Sync: Regular Sync middleware action.
"Block"
: Sync every block. Represents a BlockSync withmatchBlockNumberModulo = 1
.number
: Sync everyn
blocks. Represents a BlockSync withmatchBlockNumberModulo = n
."Transaction"
: Sync every transaction fromsender
.sender
is often another parameter in the function."once"
: Don't sync. Fetch once and never refresh call."ifnull"
: Fetch iff value in store is undefined.
Reference: GenericSync `
In summary, there are 4 types of contract call sync types:
once
: Call contract method onceBlock
: Call contract and refresh every block.Event
: Call contract onTransaction
: Call contract and refresh every time a block includes a transaction to the contract. This uses the heuristic that your contract's state only changes when transactions interact with it directly.
Both block sync, and transaction sync require an existing block subscription to be first created.
Transaction
sync's default behaviour might not be correct for your smart contract as state could be modified indirectly by the means of one smart contract calling another. See below for more info
Optimizing Call Sync
By default, contracts use Transaction syncing but this can be customized for each specific contract call. This is can be a sub-optimal or even incorrect sync strategy.
Transaction syncing can be sub-optimal if a call's return value never changes. For example, an ERC20 token's name or symbol. In this case simply disable syncing with sync: false
.
Transaction syncing assumes that the contract call values are only dependent on your contract's state and that this state is only changed by direct transactions to your contract. The basic logic for Transaction syncing is as follows: For each transaction in a new block, update contract call if tx.to == contract.address
.
Examples of cases where this assumption might be incorrect include:
- Contract call return value depends on block number
- Contract state can be changed by a call to some proxy contract
In these cases we recommend switching to Block syncing, which will poll the contract call at every block. For even better optimization, it might be interesting in some cases to use a custom block or transaction sync.
Custom Call Syncs
We recommend using Event Sync when possible as this is often the most optimal solution, only updating when the relevant state is modified.
Custom Block Sync
This might be useful as a quick solution to implement polling behaviour to the way you refresh a smart contract's data. This solution is especially optimal wfor state that depends on the block number (eg. some beacon).
//Sync every 10 blocks
Sync.create({ id: '1', type: 'Block', matchBlockNumberModulo: 10, actions });
Custom Transaction Sync
This might be useful when you know that only a set of tx.to
addresses can initiate modifying the state of the smart contract.
Sync.create({ id: '1', type: 'Transaction', matchTo: [contractAddress, proxyAddress], actions }));
Custom Event Sync
This is often the most optimal solution when you are aware of the contract's logic and how events are emitted when state is updated. As an example, the useERC20
hook, only refreshes balanceOf
calls when relevant Transfer
events are emitted.
Sync.create({
id: '1',
type: 'Event',
matchAddress: contractAddress,
matchName: 'Transfer',
matchReturnValues: [{ from: account }, { to: account }],
actions,
});