-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve SDK and Wallet Communication #3669
Comments
Have discussed further with @petertonysmith94 and we have come up with the following phased approach: Phase 1 - Estimation and Funding Phase 1 aims to give more context to the wallet as to whether it is needs to perform the estimation and funding stages. This includes the addition of the interface SendTransactionJsonRpc {
address: string,
transaction: TransactionRequest,
provider: {
url: string,
},
isEstimated: boolean,
isFunded: boolean,
isSigned: boolean,
} For the implementation, we will pass an object throughout the transaction preparation flow:
When an operation is performed that sets one of these flags, we will store the transaction hash against the flag:
On submission, the final transaction hash is then checked against the flags. If they are still valid, they are passed to the wallet. Phase 2 - Summary Generation Phase 2 will then provide more context around provider values used for estimation, that can also be used in transaction summary generation. This includes the addition of the chain and gas properties to the JSON RPC provider object: interface SendTransactionJsonRpc {
...
provider: {
...
maxInputs: BN,
estimatedGasPrice: BN,
maxGasPerTx: BN,
maxGasPerPredicate: BN,
gasPriceFactor: BN,
gasPerByte: BN,
gasCosts: GasCosts,
},
...
} For the implementation, on submission the chain parameters are grabbed from the cache and added to the transmission object.
Phase 3 - Summary on load Phase 3 will provide a complete transaction summary and/or receipts to the wallet, that will allow it to synchronously generate a summary without fetching any other information. This includes the addition of a complete transaction summary and receipts to the JSON RPC object: interface SendTransactionJsonRpc {
...
summary: TransactionSummary,
receipts: Receipt[]
} Implementation is still TBD here. |
Based on feedback in #3709 and some further investigation, we are going to update the above spec. |
Analysis of how eco-system projects are estimating and funding transactions: ScenariosIdentifying use cases React HooksThis returns an MiraPass through the gasCosts as part of the fund import {useWallet} from "@fuels/react";
// wallet: Account
const {wallet} = useWallet();
// Fund + estimate
const gasCost = await wallet.getTransactionCost(txRequest);
const fundedTx = await wallet.fund(txRequest, gasCost);
// Send
const tx = await wallet.sendTransaction(fundedTx, {
estimateTxDependencies: true,
}); GriffyUses both predicate estimates and setting of the import { useWallet } from "@fuels/react";
const { wallet } = useWallet();
// Estimate
let txCost: TransactionCost = await predicate.getTransactionCost(
transactionRequest
);
transactionRequest.updatePredicateGasUsed(txCost.estimatedPredicates);
transactionRequest.gasLimit = txCost.gasUsed;
transactionRequest.maxFee = txCost.maxFee;
// Fund
await predicate.fund(transactionRequest, txCost);
// Send
const tx = await wallet.sendTransaction(transactionRequest); Uses the const { maxFee } = await predicate.provider.estimateTxGasAndFee({
transactionRequest: requestToReestimate,
gasPrice,
});
request.maxFee = maxFee; SwaylendSetup the related contracts with the wallet import { useWallet } from '@fuels/react';
const { wallet } = useWallet();
const pythContract = new PythContract(
appConfig.markets[market].oracleAddress,
walletOrProvider
);
const marketContract = new Market(
appConfig.markets[market].marketAddress,
walletOrProvider
);
updateContracts(market, pythContract, marketContract); Perform calls on the contracts (using the above initialized contracts) const { waitForResult } = await marketContract.functions
.withdraw_base(amount.toFixed(0), priceUpdateData)
.callParams({
forward: {
amount: priceUpdateData.update_fee,
assetId: appConfig.baseAssetId,
},
})
.addContracts([pythContract])
.call(); |
State Flags Re-SpecFollowing a conversation with @petertonysmith94 on the above topic, we are currently discussing the follow spec: To describe the level of preparedness for a transaction, we shall pass a
This will be stored against the transaction request so that it is still the sole object that a user needs to pass throughout the transaction flow. We will update the state property through the tracking of the transaction hash. Consider the following flow: // State is currently `state: { value: undefined, txId: undefined }`
const txRequest = new ScriptTransactionRequest();
txRequest.addCoinOutput(sender.address, bn(1000), await provider.getBaseAssetId());
// State set to `state: { value: 'funded', txId: '0x123' }`
await txRequest.estimateAndFund(sender);
// txId is checked against `state.txId`, if it matches,
// then `state.value` is propagated to the wallet, otherwise
// `state.value` is set back to `undefined`
await sender.sendTransaction(txRequest); The phase 1 interface now looks like so: interface SendTransactionJsonRpc {
address: string,
transaction: TransactionRequest,
provider: {
url: string,
},
state: 'funded' | 'immutable',
} |
Chain Info Re-SpecPlease see PR for specification. Here we will now pass across anything that has already been fetched from the chain, include the chain configuration and an estimate/lastest gas price if they have been fetched. interface SendTransactionJsonRpc {
address: string,
transaction: TransactionRequest,
provider: {
...,
cache: {
consensusParameterTimestamp: string,
chainInfo: ChainInfo,
}
},
data: {
latestGasPrice: string,
estimatedGasPrice: string,
}
...
} To support this, we should also enable a way of initialising a provider and pass through a chain info cache, allowing it to be shared between the SDK and the wallet. const provider = new Provider(sdkJsonRpc.provider.url, { chainInfo: sdkJsonRpc.provider.chainInfo }); |
Summary Re-Specinterface SendTransactionJsonRpc {
...
summary: TransactionSummary
} For the summary, we need to only provide the After some validation and conversations with @petertonysmith94 and @Torres-ssf, we can use the receipts from the initial dry run in So if |
Problem
When a transaction is passed from an application to the wallet, the wallet performs estimation and funding network requests that have already been performed by the SDK. This can be visualised in the following diagram:
This is because the wallet has no knowledge of the state of a transaction, so attempts to account for anything that could be missing.
Solution
We should improve handoff from the SDK to connectors/wallets so that they can act accordingly, and not introduce any redundancy in the transaction flow.
Currently, the context that the SDK provides to the wallet includes:
This should be extended to:
With the following additional information, the wallet can act accordingly and should not perform any redundant network requests.
Note
The specific work that needs to be done in the SDK, Connectors and Wallet is still being worked out but will be added to this issue
The text was updated successfully, but these errors were encountered: