Skip to content
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

feat: add an option to send custom gas limit when making transfers #1318

Merged
merged 50 commits into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
d21b53b
feat: upgrade fuels to 0.88.1
helciofranco May 27, 2024
ae1b76f
Merge branch 'master' of github.com:FuelLabs/fuels-wallet into hf/fea…
helciofranco May 27, 2024
0274fb3
feat: add gas limit input back
helciofranco May 27, 2024
b430b29
fix: reset error when it receives a successful request
helciofranco May 27, 2024
71bac88
chore: remove base gas limit fake estimation
helciofranco May 27, 2024
d52a4b8
chore: display empty value when amount is zero
helciofranco May 28, 2024
860498c
Merge branch 'master' of github.com:FuelLabs/fuels-wallet into hf/fea…
helciofranco May 28, 2024
1a38036
feat: add gas limit error
helciofranco May 28, 2024
44c99dc
fix: improve gas limit and tip format
helciofranco May 28, 2024
2ff6765
fix: handle amount and human amount differently
helciofranco May 28, 2024
c5fd53f
fix: allow user to send 'negative' values
helciofranco May 28, 2024
9c41507
Merge branch 'master' of github.com:FuelLabs/fuels-wallet into hf/fea…
helciofranco May 28, 2024
e682654
docs: add changeset
helciofranco May 28, 2024
db92142
fix: tip error state
helciofranco May 28, 2024
4099b20
Merge branch 'master' into hf/feat/custom-gas-limit
helciofranco May 28, 2024
e1754f0
Merge branch 'master' into hf/feat/custom-gas-limit
helciofranco May 28, 2024
fe7dd17
feat: make gas limit and tip in two columns
helciofranco May 28, 2024
7b96b8c
feat: add initial gas limit
helciofranco May 28, 2024
b6f4456
feat: add estimation while editing gas limit and tip
helciofranco May 28, 2024
9d92b5e
fix: hide api error message
helciofranco May 29, 2024
33b8f05
fix: get tx cost to fetch min gas limit
helciofranco May 29, 2024
94b0e20
chore: fetch max fee from the same source of truth
helciofranco May 29, 2024
2568628
chore: fetch max fee from the tx request actually
helciofranco May 29, 2024
84f7e31
fix: improve user experience
helciofranco May 29, 2024
c98c03f
fix: prevent to validate form before the needed
helciofranco May 29, 2024
0973ea2
fix: set checked UI
helciofranco May 31, 2024
3450dc4
Merge branch 'master' into hf/feat/custom-gas-limit
helciofranco May 31, 2024
3645e3f
Merge branch 'master' into hf/feat/custom-gas-limit
LuizAsFight May 31, 2024
14a0daa
Merge branch 'master' into hf/feat/custom-gas-limit
helciofranco Jun 3, 2024
b09e418
Merge branch 'master' into hf/feat/custom-gas-limit
helciofranco Jun 4, 2024
bb69672
Merge branch 'master' of github.com:FuelLabs/fuels-wallet into hf/fea…
helciofranco Jun 5, 2024
791f817
Merge branch 'hf/feat/custom-gas-limit' of github.com:FuelLabs/fuels-…
helciofranco Jun 5, 2024
b653ddc
fix: rephrase gas limit errors
helciofranco Jun 5, 2024
22fbffb
fix: control min and max tip value
helciofranco Jun 5, 2024
225de9e
fix: adjust animations
helciofranco Jun 5, 2024
af42c07
feat: add animation to amount error
helciofranco Jun 5, 2024
4a49f5d
fix: show tip error when needed
helciofranco Jun 5, 2024
4389b62
chore: smooth transitions
helciofranco Jun 5, 2024
385e1db
fix: typescript
helciofranco Jun 5, 2024
aed719d
chore: refresh lockfile
helciofranco Jun 5, 2024
4547a37
Merge branch 'master' into hf/feat/custom-gas-limit
helciofranco Jun 11, 2024
42c3abd
fix: audit
helciofranco Jun 19, 2024
a1d0cb7
Merge branch 'master' of github.com:FuelLabs/fuels-wallet into hf/fea…
helciofranco Jun 20, 2024
2b11039
Merge branch 'master' into hf/feat/custom-gas-limit
helciofranco Jun 26, 2024
1648933
Merge branch 'master' of github.com:FuelLabs/fuels-wallet into hf/fea…
helciofranco Jun 27, 2024
5f5eeae
fix: add missing import
helciofranco Jun 27, 2024
1a6d6d7
Merge branch 'master' into hf/feat/custom-gas-limit
helciofranco Jun 28, 2024
0630e28
Merge branch 'master' into hf/feat/custom-gas-limit
helciofranco Jun 29, 2024
7e73c91
Merge branch 'master' into hf/feat/custom-gas-limit
helciofranco Jul 8, 2024
a1edfa5
Merge branch 'master' of github.com:FuelLabs/fuels-wallet into hf/fea…
helciofranco Jul 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/young-jokes-dream.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@fuel-wallet/connections": minor
"@fuel-wallet/types": minor
"fuels-wallet": minor
---

Add `Gas Limit` input to customize transaction fees when sending a transfer
4 changes: 2 additions & 2 deletions fuel-toolchain.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
channel = "latest-2023-11-30"

[components]
fuel-core = "0.24.3"
forc = "0.56.0"
fuel-core = "0.26.0"
forc = "0.59.0"
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export function SendSelect({
balanceAssets,
balanceAssetSelected,
baseFee = bn(0),
baseGasLimit = bn(0),
minGasLimit = bn(0),
tip,
regularTip,
fastTip,
Expand Down Expand Up @@ -62,10 +62,9 @@ export function SendSelect({
// Adding 2 magical units to match the fake unit that is added on TS SDK (.add(1))
// and then removed on the "transaction" service (.sub(1))
const maxFee = baseFee.add(tip).add(2);
if (maxFee.gt(balanceAssetSelected)) return;

form.setValue('amount', balanceAssetSelected.sub(maxFee), {
shouldValidate: true,
});
form.setValue('amount', balanceAssetSelected.sub(maxFee));
}
}, [watchMax, balanceAssetSelected, baseFee, tip, form.setValue]);

Expand Down Expand Up @@ -164,7 +163,7 @@ export function SendSelect({
</Text>
<TxFeeOptions
baseFee={baseFee}
baseGasLimit={baseGasLimit}
minGasLimit={minGasLimit}
regularTip={regularTip}
fastTip={fastTip}
/>
Expand Down
208 changes: 126 additions & 82 deletions packages/app/src/systems/Send/hooks/useSend.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ export enum SendStatus {
}

const selectors = {
baseGasLimit(state: SendMachineState) {
return state.context.baseGasLimit;
minGasLimit(state: SendMachineState) {
return state.context.minGasLimit;
},
maxGasPerTx(state: SendMachineState) {
return state.context.maxGasPerTx;
maxGasLimit(state: SendMachineState) {
return state.context.maxGasLimit;
},
baseFee(state: SendMachineState) {
return state.context.baseFee;
Expand All @@ -42,6 +42,10 @@ const selectors = {
return state.matches('readyToSend');
},
error(state: SendMachineState) {
if (state.context.error?.includes('Gas limit')) {
return '';
}

return state.context.error;
},
status(txStatus?: TxRequestStatus) {
Expand All @@ -60,13 +64,16 @@ const selectors = {
},
};

type BalanceAsset = {
assetId: string;
amount?: BNInput;
};

type SchemaOptions = {
accountBalanceAssets: Array<{
assetId: string;
amount?: BNInput;
}>;
accountBalanceAssets: BalanceAsset[];
baseFee: BN | undefined;
maxGasPerTx: BN | undefined;
minGasLimit: BN | undefined;
maxGasLimit: BN | undefined;
};

const schema = yup
Expand Down Expand Up @@ -98,7 +105,7 @@ const schema = yup
return true;
}

const totalAmount = value.add(baseFee.add(fees.tip));
const totalAmount = value.add(baseFee.add(fees.tip.amount));
return totalAmount.lte(bn(balanceAssetSelected.amount));
})
.required('Amount is required'),
Expand All @@ -114,41 +121,63 @@ const schema = yup
}),
fees: yup
.object({
tip: yup
.mixed<BN>()
.test(
'integer',
'Tip must be greater than or equal to 0',
(value) => {
return value?.gte(0);
}
)
.required('Tip is required'),
gasLimit: yup
.mixed<BN>()
.test(
'integer',
'Gas limit must be greater or equal to 0',
(value) => {
return value?.gte(0);
}
)
.test({
name: 'max',
test: (value, ctx) => {
const { maxGasPerTx } = ctx.options.context as SchemaOptions;
if (!maxGasPerTx) return false;

if (value?.lte(maxGasPerTx)) {
return true;
tip: yup.object({
amount: yup
.mixed<BN>()
.test(
'integer',
'Tip must be greater than or equal to 0',
(value) => {
return value?.gte(0);
}

return ctx.createError({
message: `Gas limit must be less or equal to ${maxGasPerTx.toString()}`,
});
},
})
.required('Gas limit is required'),
)
.required('Tip is required'),
text: yup.string().required('Tip is required'),
}),
gasLimit: yup.object({
amount: yup
.mixed<BN>()
.test(
'integer',
'Gas limit must be greater or equal to 0',
(value) => {
return value?.gte(0);
}
)
.test({
name: 'min',
test: (value, ctx) => {
const { minGasLimit } = ctx.options.context as SchemaOptions;

if (!minGasLimit || value?.gte(minGasLimit)) {
return true;
}

return ctx.createError({
path: 'fees.gasLimit',
message: `Gas limit '${value?.toString()}' is lower than the required: '${minGasLimit.toString()}'.`,
});
},
})
.test({
name: 'max',
test: (value, ctx) => {
const { maxGasLimit } = ctx.options.context as SchemaOptions;
if (!maxGasLimit) return false;

if (value?.lte(maxGasLimit)) {
return true;
}

return ctx.createError({
path: 'fees.gasLimit',
message: `Gas limit '${value?.toString()}' is greater than the allowed: '${maxGasLimit.toString()}'.`,
});
},
})
.required('Gas limit is required'),
text: yup.string().required('Gas limit is required'),
}),
})
.required('Fees are required'),
})
Expand All @@ -159,8 +188,14 @@ export type SendFormValues = {
address: string;
amount: BN;
fees: {
tip: BN;
gasLimit: BN;
tip: {
amount: BN;
text: string;
};
gasLimit: {
amount: BN;
text: string;
};
};
};

Expand All @@ -169,8 +204,14 @@ const DEFAULT_VALUES: SendFormValues = {
amount: bn(0),
address: '',
fees: {
tip: bn(0),
gasLimit: bn(0),
tip: {
amount: bn(0),
text: '0',
},
gasLimit: {
amount: bn(0),
text: '0',
},
},
};

Expand Down Expand Up @@ -203,42 +244,27 @@ export function useSend() {
);

const baseFee = useSelector(service, selectors.baseFee);
const baseGasLimit = useSelector(service, selectors.baseGasLimit);
const maxGasPerTx = useSelector(service, selectors.maxGasPerTx);
const minGasLimit = useSelector(service, selectors.minGasLimit);
const maxGasLimit = useSelector(service, selectors.maxGasLimit);
const errorMessage = useSelector(service, selectors.error);

const form = useForm<SendFormValues>({
resolver: yupResolver(schema),
reValidateMode: 'onChange',
mode: 'onChange',
mode: 'onSubmit',
defaultValues: DEFAULT_VALUES,
context: {
accountBalanceAssets,
baseFee,
maxGasPerTx,
minGasLimit,
maxGasLimit,
},
});

const tip = useWatch({
control: form.control,
name: 'fees.tip',
name: 'fees.tip.amount',
});

const gasLimit = useWatch({
control: form.control,
name: 'fees.gasLimit',
});

const { isValid } = form.formState;

const amount = useWatch({
control: form.control,
name: 'amount',
});
const address = useWatch({
control: form.control,
name: 'address',
});
const assetIdSelected = useWatch({
control: form.control,
name: 'asset',
Expand Down Expand Up @@ -286,23 +312,41 @@ export function useSend() {
}

useEffect(() => {
if (isValid && address && assetIdSelected) {
const input: TxInputs['createTransfer'] = {
to: address,
assetId: assetIdSelected,
amount,
tip,
gasLimit,
};

service.send('SET_INPUT', { input });
}
}, [isValid, service.send, address, assetIdSelected, amount, tip, gasLimit]);
const { unsubscribe } = form.watch(() => {
const { address, asset, amount } = form.getValues();
if (!address || !asset || amount.eq(0)) {
return;
}

form.handleSubmit((data) => {
const { address, asset, amount, fees } = data;

const input: TxInputs['createTransfer'] = {
to: address,
assetId: asset,
amount,
tip: fees.tip.amount,
gasLimit: fees.gasLimit.amount,
};

service.send('SET_INPUT', { input });
form.trigger('amount');
})();
});

return () => unsubscribe();
}, [
form.watch,
form.getValues,
form.trigger,
form.handleSubmit,
service.send,
]);

return {
form,
baseFee,
baseGasLimit,
minGasLimit,
tip,
regularTip,
fastTip,
Expand Down
19 changes: 11 additions & 8 deletions packages/app/src/systems/Send/machines/sendMachine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ export type MachineContext = {
providerUrl?: string;
address?: string;
baseFee?: BN;
baseGasLimit?: BN;
regularTip?: BN;
fastTip?: BN;
maxGasPerTx?: BN;
minGasLimit?: BN;
maxGasLimit?: BN;
input?: TxInputs['createTransfer'];
error?: string;
};
Expand All @@ -34,12 +34,12 @@ type EstimateDefaultTipsReturn = {
};

type EstimateGasLimitReturn = {
baseGasLimit: BN;
maxGasPerTx: BN;
maxGasLimit: BN;
};

type CreateTransactionReturn = {
baseFee?: BN;
minGasLimit?: BN;
transactionRequest?: TransactionRequest;
providerUrl: string;
address: string;
Expand Down Expand Up @@ -168,19 +168,22 @@ export const sendMachine = createMachine(
assignDefaultTips: assign((_ctx, ev) => ({
regularTip: ev.data.regularTip,
fastTip: ev.data.fastTip,
error: undefined,
})),
assignGasLimit: assign((_ctx, ev) => ({
baseGasLimit: ev.data.baseGasLimit,
maxGasPerTx: ev.data.maxGasPerTx,
maxGasLimit: ev.data.maxGasLimit,
error: undefined,
})),
assignInput: assign((_ctx, ev) => ({
input: ev.input,
})),
assignTransactionData: assign((_ctx, ev) => ({
assignTransactionData: assign((ctx, ev) => ({
transactionRequest: ev.data.transactionRequest,
providerUrl: ev.data.providerUrl,
address: ev.data.address,
baseFee: ev.data.baseFee,
baseFee: ev.data.baseFee ?? ctx.baseFee,
minGasLimit: ev.data.minGasLimit ?? ctx.minGasLimit,
error: undefined,
})),
},
services: {
Expand Down
Loading
Loading