Skip to content

Commit

Permalink
add token + amount inputs to migrate job dialog + adapt logic for fun…
Browse files Browse the repository at this point in the history
…ding job
  • Loading branch information
simke9445 committed Mar 16, 2024
1 parent 2149efa commit 17f82d7
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import { Job } from 'types';
import { NumericInput } from 'components/primitives/numeric-input';
import { useMigrateJobForm } from './useMigrateJobForm';
import { FundingAccountInput } from './funding-account-input/FundingAccountInput';
import { TokenInput } from 'pages/balances/token-input/TokenInput';
import { AmountInput } from 'pages/dashboard/jobs-widget/inputs/AmountInput';
import { demicrofy, microfy } from '@terra-money/apps/libs/formatting';
import Big from 'big.js';

type MigrateJobDialogProps = {
job: Job;
Expand All @@ -18,14 +22,19 @@ export const MigrateJobDialog = (props: DialogProps<MigrateJobDialogProps, boole

const [txResult, migrateJobTx] = useMigrateJobTx(true);

const [input, { durationDays, submitDisabled, fundingAccount }] = useMigrateJobForm();
const [
input,
{ durationDays, submitDisabled, fundingAccount, token, amount, amountError, balance, balanceLoading, amountValid },
] = useMigrateJobForm();

return (
<Dialog className={styles.root}>
<DialogHeader title="Migrate job" onClose={() => closeDialog(undefined, { closeAll: true })} />
<DialogBody className={styles.body}>
<Text variant="label" className={styles.description}>
You may specify additional fields such as duration of stay or optionally attach a funding account.
You may specify additional fields such as duration of stay, optional funding account or job funds. Job funds
are drawn from the wallet. In case you want to provide Warp account funds, first withdraw the assets to your
wallet.
</Text>
<FormControl className={styles.duration_days_input} label="Duration (in days)">
<NumericInput
Expand All @@ -39,11 +48,45 @@ export const MigrateJobDialog = (props: DialogProps<MigrateJobDialogProps, boole
/>
</FormControl>
<FundingAccountInput
optional={true}
className={styles.funding_account}
label="Funding account"
value={fundingAccount}
onChange={(acc) => input({ fundingAccount: acc })}
/>
<TokenInput
optional={true}
className={styles.token_input}
label="Token"
value={token}
onChange={(token) => {
input({ token });
}}
/>

<AmountInput
optional={true}
label="Amount"
className={styles.amount_input}
value={amount}
onChange={(value) =>
input({
amount: value.target.value,
})
}
onBalanceClick={(value) => {
if (token) {
input({
amount: demicrofy(value, token?.decimals).toString(),
});
}
}}
error={amountError}
balance={balance}
balanceLoading={balanceLoading}
token={token}
valid={amountValid}
/>
</DialogBody>
<DialogFooter>
<Button
Expand All @@ -52,7 +95,9 @@ export const MigrateJobDialog = (props: DialogProps<MigrateJobDialogProps, boole
disabled={submitDisabled}
loading={txResult.loading}
onClick={async () => {
const result = await migrateJobTx({ job, durationDays, fundingAccount });
let parsedAmount = token && amount ? microfy(Big(amount), token?.decimals) : undefined;

const result = await migrateJobTx({ job, durationDays, fundingAccount, amount: parsedAmount, token });

if (result.code !== 0) {
closeDialog(true);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,42 +1,107 @@
import { FormFunction, FormState, useForm } from '@terra-money/apps/hooks';
import { useMemo } from 'react';
import { FormFunction, FormModifier, FormState, LocalWallet, useForm, useLocalWallet } from '@terra-money/apps/hooks';
import { warp_controller } from '@terra-money/warp-sdk-v2';
import { Token, u } from '@terra-money/apps/types';
import Big from 'big.js';
import { microfy } from '@terra-money/apps/libs/formatting';
import { fetchTokenBalance } from '@terra-money/apps/queries';

export interface MigrateJobFormInput {
durationDays: string;
fundingAccount?: string;
cwFunds?: warp_controller.CwFund[];
nativeFunds?: warp_controller.Coin[];
token?: Token;
amount?: string;
}

interface MigrateJobFormState extends FormState<MigrateJobFormInput> {
submitDisabled: boolean;
amountValid?: boolean;
amountError?: string;
balance: u<Big>;
balanceLoading: boolean;
}

export const useMigrateJobForm = (input?: MigrateJobFormInput) => {
const initialValue = useMemo<MigrateJobFormState>(
() => ({
durationDays: input?.durationDays ?? '',
submitDisabled: input ? false : true,
}),
[input]
);
const dispatchTokenBalance = (
token: Token | undefined,
localWallet: LocalWallet,
dispatch: FormModifier<MigrateJobFormState>
) => {
dispatch({
amount: '',
balance: Big(0) as u<Big>,
balanceLoading: true,
});

fetchTokenBalance(localWallet.lcd, token, localWallet.walletAddress)
.then((balance) => {
dispatch({
balance,
balanceLoading: false,
});
})
.catch(() => {
dispatch({
balance: Big(0) as u<Big>,
balanceLoading: false,
});
});
};

const initialValue: MigrateJobFormState = {
durationDays: '',
fundingAccount: undefined,
submitDisabled: true,
token: undefined,
balance: Big(0) as u<Big>,
balanceLoading: false,
amount: '',
};

export const useMigrateJobForm = () => {
const wallet = useLocalWallet();

const form: FormFunction<MigrateJobFormInput, MigrateJobFormState> = async (input, getState, dispatch) => {
if (wallet.connectedWallet === undefined) {
throw Error('The wallet is not connected');
}

if ('token' in input) {
dispatchTokenBalance(input.token, wallet, dispatch);
}

const state = {
...getState(),
...input,
};

const submitDisabled = Boolean(
state.durationDays === undefined || state.durationDays === null || state.durationDays.length < 1
);
const uAmount = state.token && input.amount ? microfy(input.amount, state.token.decimals) : Big(0);

const amountError = uAmount.gt(state.balance) ? 'The amount can not exceed the maximum balance' : undefined;

const amountValid = uAmount.gt(0) && amountError === undefined;

const submitDisabled =
Boolean(state.token && amountValid === false) ||
state.durationDays === undefined ||
state.durationDays === null ||
state.durationDays.length < 1;

dispatch({
...state,
amountError,
amountValid,
submitDisabled,
});
};

return useForm<MigrateJobFormInput, MigrateJobFormState>(form, initialValue);
return useForm<MigrateJobFormInput, MigrateJobFormState>(form, initialValue, async (state, dispatch) => {
if (wallet.connectedWallet === undefined) {
throw Error('The wallet is not connected');
}

if (state.token) {
dispatchTokenBalance(state.token, wallet, dispatch);
}
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ import styles from './TokenInput.module.sass';

interface TokenInputProps extends UIElementProps {
label: string;
optional?: boolean;
placeholder?: string;
value?: Token;
onChange: (value: Token) => void;
}

const TokenInput = (props: TokenInputProps) => {
const { className, placeholder = 'Select a token', label, value, onChange } = props;
const { className, placeholder = 'Select a token', label, value, onChange, optional } = props;

const openTokenList = useTokenListDialog();

Expand All @@ -32,7 +33,7 @@ const TokenInput = (props: TokenInputProps) => {
);

return (
<FormControl className={classNames(className, styles.root)} label={label}>
<FormControl className={classNames(className, styles.root)} label={label} optional={optional}>
<Container
className={styles.container}
direction="row"
Expand Down
31 changes: 27 additions & 4 deletions apps/warp-protocol/src/tx/useMigrateJobTx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@ import { useWarpSdk, useWarpSdkv2 } from '@terra-money/apps/hooks';
import { Job } from 'types';
import { composers, warp_resolver as warp_resolver_v2, Execution } from '@terra-money/warp-sdk-v2';
import { warp_resolver } from '@terra-money/warp-sdk';
import { Coin } from '@terra-money/feather.js';
import { Coin, Coins } from '@terra-money/feather.js';
import { Token, u } from '@terra-money/apps/types';
import Big from 'big.js';

interface MigrateJobTxProps {
job: Job;
durationDays: string;
fundingAccount?: string;
amount?: u<Big>;
token?: Token;
}

const mapVars = (vars: warp_resolver.Variable[]): warp_resolver_v2.Variable[] => {
Expand Down Expand Up @@ -45,7 +49,7 @@ export const useMigrateJobTx = (waitForCompletion?: boolean) => {

return useTx<MigrateJobTxProps>(
async (options) => {
const { wallet, job, durationDays, fundingAccount } = options;
const { wallet, job, durationDays, fundingAccount, token, amount } = options;

const walletAddress = wallet.walletAddress;

Expand Down Expand Up @@ -75,7 +79,7 @@ export const useMigrateJobTx = (waitForCompletion?: boolean) => {

const operationalAmount = operationalAmountEstimate.amount.toString();

const createJobMsg = composers.job
let createJobMsg = composers.job
.create()
.name(job.info.name)
.labels(job.info.labels)
Expand All @@ -89,7 +93,26 @@ export const useMigrateJobTx = (waitForCompletion?: boolean) => {
.executions(executions)
.compose();

const coins = fundingAccount ? [] : [new Coin(nativeTokenDenom, operationalAmount)];
let coins = new Coins();

if (token && amount) {
if (token.type === 'cw20') {
createJobMsg.cw_funds = [
{
cw20: {
contract_addr: token.token,
amount: amount.toString(),
},
},
];
} else {
coins = coins.add(new Coin(token.denom, amount.toString()));
}
}

if (!fundingAccount) {
coins = coins.add(new Coin(nativeTokenDenom, operationalAmount.toString()));
}

const createJobV2Tx = await sdkv2.tx.createJob(wallet.walletAddress, createJobMsg, coins);
const deleteJobV1Tx = await sdkv1.tx.deleteJob(wallet.walletAddress, job.info.id);
Expand Down

0 comments on commit 17f82d7

Please sign in to comment.