Skip to content

Commit

Permalink
refactor: refund address input (#796)
Browse files Browse the repository at this point in the history
* refactor: split `RefundBtc` component from `RefundButton`

* refactor: refund address input

* fix: check refund address in effect instead of input event handler to react to swap changes

* chore: rm custom validity calls

these messages are never displayed
  • Loading branch information
jackstar12 authored Jan 12, 2025
1 parent 75d834f commit 53b7d18
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 83 deletions.
163 changes: 84 additions & 79 deletions src/components/RefundButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@ import { Network as LiquidNetwork } from "liquidjs-lib/src/networks";
import log from "loglevel";
import {
Accessor,
Match,
Setter,
Show,
Switch,
createEffect,
createResource,
createSignal,
} from "solid-js";
Expand Down Expand Up @@ -109,7 +108,7 @@ export const RefundEvm = (props: {
);
};

const RefundButton = (props: {
export const RefundBtc = (props: {
swap: Accessor<SubmarineSwap | ChainSwap>;
setRefundTxId?: Setter<string>;
buttonOverride?: string;
Expand All @@ -123,6 +122,7 @@ const RefundButton = (props: {
t,
} = useGlobalContext();
const { setSwap } = usePayContext();

const [timeoutEta, setTimeoutEta] = createSignal<number | null>(null);
const [timeoutBlockheight, setTimeoutBlockheight] = createSignal<
number | null
Expand All @@ -131,35 +131,31 @@ const RefundButton = (props: {
const [valid, setValid] = createSignal<boolean>(false);
const [refundRunning, setRefundRunning] = createSignal<boolean>(false);

const refundAddressChange = (evt: InputEvent, asset: string) => {
const input = evt.currentTarget as HTMLInputElement;
const inputValue = input.value.trim();
createEffect(() => {
const asset = props.swap()?.assetSend;
if (!asset) return;

const lockupAddress =
props.swap().type === SwapType.Submarine
? (props.swap() as SubmarineSwap).address
: (props.swap() as ChainSwap).lockupDetails.lockupAddress;

if (inputValue === lockupAddress) {
if (refundAddress() === lockupAddress) {
log.debug("refunds to lockup address are blocked");
input.setCustomValidity("lockup address");
return false;
}
try {
getAddress(asset).toOutputScript(
inputValue,
getNetwork(asset) as LiquidNetwork,
);
input.setCustomValidity("");
setRefundAddress(inputValue);
return true;
} catch (e) {
log.debug("parsing refund address failed", e);
input.setCustomValidity("invalid address");
setValid(false);
} else {
try {
getAddress(asset).toOutputScript(
refundAddress(),
getNetwork(asset) as LiquidNetwork,
);
setValid(true);
} catch (e) {
log.debug("parsing refund address failed", e);
setValid(false);
}
}

return false;
};
});

const refundAction = async () => {
setRefundRunning(true);
Expand Down Expand Up @@ -234,6 +230,69 @@ const RefundButton = (props: {
return transactionToRefund;
});

const buttonMessage = () => {
if (lockupTransaction.state == "errored") {
return t("no_lockup_transaction");
}
if (valid() || !refundAddress() || !props.swap()) {
return t("refund");
}
return t("invalid_address", { asset: props.swap()?.assetSend });
};

return (
<Show
when={
lockupTransaction.state === "ready" ||
lockupTransaction.state == "unresolved" ||
lockupTransaction.state == "errored"
}
fallback={<LoadingSpinner />}>
<Show when={timeoutEta() > 0 || timeoutBlockheight() > 0}>
<RefundEta
timeoutEta={timeoutEta}
timeoutBlockHeight={timeoutBlockheight}
/>
</Show>
<h3 style={{ color: "#fff" }}>
{props.swap()
? t("refund_address_header", {
asset: props.swap()?.assetSend,
})
: t("refund_address_header_no_asset")}
</h3>
<input
data-testid="refundAddress"
id="refundAddress"
disabled={lockupTransaction.state == "errored"}
value={refundAddress()}
onInput={(e) => setRefundAddress(e.target.value.trim())}
type="text"
name="refundAddress"
placeholder={
props.swap()
? t("onchain_address", {
asset: props.swap()?.assetSend,
})
: t("onchain_address_no_asset")
}
/>
<button
data-testid="refundButton"
class="btn"
disabled={!valid() || refundRunning()}
onClick={() => refundAction()}>
{props.buttonOverride ?? buttonMessage()}
</button>
</Show>
);
};

const RefundButton = (props: {
swap: Accessor<SubmarineSwap | ChainSwap>;
setRefundTxId?: Setter<string>;
buttonOverride?: string;
}) => {
const [preimageHash] = createResource(async () => {
return (await decodeInvoice((props.swap() as SubmarineSwap).invoice))
.preimageHash;
Expand Down Expand Up @@ -295,61 +354,7 @@ const RefundButton = (props: {
</Show>
</Show>
}>
<Switch>
<Match
when={
lockupTransaction.state === "ready" ||
lockupTransaction.state == "unresolved"
}>
<Show when={timeoutEta() > 0 || timeoutBlockheight() > 0}>
<RefundEta
timeoutEta={timeoutEta}
timeoutBlockHeight={timeoutBlockheight}
/>
</Show>
<h3 style={{ color: "#fff" }}>
{props.swap()
? t("refund_address_header", {
asset: props.swap()?.assetSend,
})
: t("refund_address_header_no_asset")}
</h3>
<input
data-testid="refundAddress"
id="refundAddress"
disabled={props.swap() === null}
onInput={(e) =>
setValid(
refundAddressChange(e, props.swap()?.assetSend),
)
}
type="text"
name="refundAddress"
placeholder={
props.swap()
? t("onchain_address", {
asset: props.swap()?.assetSend,
})
: t("onchain_address_no_asset")
}
/>
<button
data-testid="refundButton"
class="btn"
disabled={!valid() || refundRunning()}
onClick={() => refundAction()}>
{props.buttonOverride ?? t("refund")}
</button>
</Match>
<Match when={lockupTransaction.state === "pending"}>
<LoadingSpinner />
</Match>
<Match when={lockupTransaction.state === "errored"}>
<button class="btn" disabled={true}>
{t("no_lockup_transaction")}
</button>
</Match>
</Switch>
<RefundBtc {...props} />
</Show>
);
};
Expand Down
4 changes: 0 additions & 4 deletions src/pages/RefundExternal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,12 @@ export const RefundBtcLike = () => {
} catch (e) {
log.warn("Refund json validation failed", e);
setRefundInvalid(RefundError.InvalidData);
input.setCustomValidity(t("invalid_refund_file"));
}
};

const uploadChange = async (e: Event) => {
const input = e.currentTarget as HTMLInputElement;
const inputFile = input.files[0];
input.setCustomValidity("");
setRefundJson(null);
setRefundInvalid(undefined);

Expand All @@ -74,7 +72,6 @@ export const RefundBtcLike = () => {
} catch (e) {
log.error("invalid QR code upload", e);
setRefundInvalid(RefundError.InvalidData);
input.setCustomValidity(t("invalid_refund_file"));
}
} else {
try {
Expand All @@ -83,7 +80,6 @@ export const RefundBtcLike = () => {
} catch (e) {
log.error("invalid file upload", e);
setRefundInvalid(RefundError.InvalidData);
input.setCustomValidity(t("invalid_refund_file"));
}
}
};
Expand Down

0 comments on commit 53b7d18

Please sign in to comment.