Skip to content

Commit

Permalink
Merge branch 'delivan/keplr-522' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
Thunnini committed Nov 7, 2024
2 parents 9903010 + 46003f2 commit adfc2b1
Show file tree
Hide file tree
Showing 10 changed files with 433 additions and 21 deletions.
5 changes: 5 additions & 0 deletions apps/extension/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ import { ActivitiesPage } from "./pages/activities";
import { isRunningInSidePanel } from "./utils";
import { StarknetSendPage } from "./pages/starknet/send";
import { SignStarknetTxPage } from "./pages/starknet/sign/tx";
import { SignStarknetMessagePage } from "./pages/starknet/sign/message";

configure({
enforceActions: "always", // Make mobx to strict mode.
Expand Down Expand Up @@ -472,6 +473,10 @@ const RoutesAfterReady: FunctionComponent = observer(() => {
path="/sign-starknet-tx"
element={<SignStarknetTxPage />}
/>
<Route
path="/sign-starknet-message"
element={<SignStarknetMessagePage />}
/>
<Route path="/wallet/select" element={<WalletSelectPage />} />
<Route path="/wallet/delete" element={<WalletDeletePage />} />
<Route
Expand Down
28 changes: 28 additions & 0 deletions apps/extension/src/pages/starknet/sign/message/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React, { FunctionComponent } from "react";
import { useStore } from "../../../../stores";
import { useInteractionInfo } from "../../../../hooks";
import { Splash } from "../../../../components/splash";
import { SignStarknetMessageView } from "./view";
import { observer } from "mobx-react-lite";

export const SignStarknetMessagePage: FunctionComponent = observer(() => {
const { signStarknetMessageInteractionStore } = useStore();

useInteractionInfo(() => {
signStarknetMessageInteractionStore.rejectAll();
});

return (
<React.Fragment>
{/* CosmosTxView의 주석을 꼭 읽으셈 */}
{signStarknetMessageInteractionStore.waitingData ? (
<SignStarknetMessageView
key={signStarknetMessageInteractionStore.waitingData.id}
interactionData={signStarknetMessageInteractionStore.waitingData}
/>
) : (
<Splash />
)}
</React.Fragment>
);
});
211 changes: 211 additions & 0 deletions apps/extension/src/pages/starknet/sign/message/view.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
import React, { FunctionComponent, useState } from "react";
import { SignStarknetMessageInteractionStore } from "@keplr-wallet/stores-core";
import { handleExternalInteractionWithNoProceedNext } from "../../../../utils";
import { observer } from "mobx-react-lite";
import { useStore } from "../../../../stores";
import { useInteractionInfo } from "../../../../hooks";
import { useUnmount } from "../../../../hooks/use-unmount";
import { BackButton } from "../../../../layouts/header/components";
import { HeaderLayout } from "../../../../layouts/header";
import { FormattedMessage, useIntl } from "react-intl";
import { Box } from "../../../../components/box";
import { ColorPalette } from "../../../../styles";
import { useTheme } from "styled-components";
import { Body3, H5 } from "../../../../components/typography";
import { XAxis, YAxis } from "../../../../components/axis";
import { Gutter } from "../../../../components/gutter";
import { Image } from "../../../../components/image";
import SimpleBar from "simplebar-react";

export const SignStarknetMessageView: FunctionComponent<{
interactionData: NonNullable<
SignStarknetMessageInteractionStore["waitingData"]
>;
}> = observer(({ interactionData }) => {
const { signStarknetMessageInteractionStore } = useStore();

const theme = useTheme();

const { chainStore } = useStore();

const intl = useIntl();
const interactionInfo = useInteractionInfo();

const chainId = interactionData.data.chainId;

const modularChainInfo = chainStore.getModularChain(chainId);
if (!("starknet" in modularChainInfo)) {
throw new Error(`${modularChainInfo.chainId} is not starknet chain`);
}

const [unmountPromise] = useState(() => {
let resolver: () => void;
const promise = new Promise<void>((resolve) => {
resolver = resolve;
});

return {
promise,
resolver: resolver!,
};
});

useUnmount(() => {
unmountPromise.resolver();
});

const approve = async () => {
try {
await signStarknetMessageInteractionStore.approveWithProceedNext(
interactionData.id,
interactionData.data.message,
async (proceedNext) => {
if (!proceedNext) {
if (
interactionInfo.interaction &&
!interactionInfo.interactionInternal
) {
handleExternalInteractionWithNoProceedNext();
}
}

if (
interactionInfo.interaction &&
interactionInfo.interactionInternal
) {
// XXX: 약간 난해한 부분인데
// 내부의 tx의 경우에는 tx 이후의 routing을 요청한 쪽에서 처리한다.
// 하지만 tx를 처리할때 tx broadcast 등의 과정이 있고
// 서명 페이지에서는 이러한 과정이 끝났는지 아닌지를 파악하기 힘들다.
// 만약에 밑과같은 처리를 하지 않으면 interaction data가 먼저 지워지면서
// 화면이 깜빡거리는 문제가 발생한다.
// 이 문제를 해결하기 위해서 내부의 tx는 보내는 쪽에서 routing을 잘 처리한다고 가정하고
// 페이지를 벗어나고 나서야 data를 지우도록한다.
await unmountPromise.promise;
}
},
{
// XXX: 단지 special button의 애니메이션을 보여주기 위해서 delay를 넣음...ㅋ;
preDelay: 200,
}
);
} catch (e) {
console.log(e);
}
};

return (
<HeaderLayout
title={intl.formatMessage({ id: "page.sign.cosmos.tx.title" })}
fixedHeight={true}
left={
<BackButton
hidden={
interactionInfo.interaction && !interactionInfo.interactionInternal
}
/>
}
// 유저가 enter를 눌러서 우발적으로(?) approve를 누르지 않도록 onSubmit을 의도적으로 사용하지 않았음.
bottomButton={{
isSpecial: true,
text: intl.formatMessage({ id: "button.approve" }),
size: "large",
onClick: approve,
}}
>
<Box
height="100%"
padding="0.75rem"
paddingBottom="0"
style={{
overflow: "auto",
}}
>
<Box
padding="1rem"
backgroundColor={
theme.mode === "light"
? ColorPalette.white
: ColorPalette["gray-600"]
}
borderRadius="0.375rem"
style={{
boxShadow:
theme.mode === "light"
? "0px 1px 4px 0px rgba(43, 39, 55, 0.10)"
: "none",
}}
>
<XAxis alignY="center">
<Image
alt="sign-custom-image"
src={require("../../../../public/assets/img/sign-adr36.png")}
style={{ width: "3rem", height: "3rem" }}
/>
<Gutter size="0.75rem" />
<YAxis>
<H5
color={
theme.mode === "light"
? ColorPalette["gray-500"]
: ColorPalette["gray-10"]
}
>
<FormattedMessage id="Prove account ownership to" />
</H5>
<Gutter size="2px" />
<Body3
color={
theme.mode === "light"
? ColorPalette["gray-300"]
: ColorPalette["gray-200"]
}
>
{interactionData?.data.origin || ""}
</Body3>
</YAxis>
</XAxis>
</Box>

<Gutter size="0.75rem" />
<SimpleBar
autoHide={false}
style={{
display: "flex",
flexDirection: "column",
flex: "0 1 auto",
overflowY: "auto",
overflowX: "hidden",
borderRadius: "0.375rem",
backgroundColor:
theme.mode === "light"
? ColorPalette.white
: ColorPalette["gray-600"],
boxShadow:
theme.mode === "light"
? "0px 1px 4px 0px rgba(43, 39, 55, 0.10)"
: "none",
}}
>
<Box
as={"pre"}
padding="1rem"
// Remove normalized style of pre tag
margin="0"
style={{
width: "fit-content",
color:
theme.mode === "light"
? ColorPalette["gray-400"]
: ColorPalette["gray-200"],
whiteSpace: "pre-wrap",
wordBreak: "break-all",
}}
>
{JSON.stringify(interactionData.data.message, null, 2)}
</Box>
</SimpleBar>
</Box>
</HeaderLayout>
);
});
4 changes: 4 additions & 0 deletions apps/extension/src/stores/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import {
PermissionManagerStore,
SignEthereumInteractionStore,
SignStarknetTxInteractionStore,
SignStarknetMessageInteractionStore,
} from "@keplr-wallet/stores-core";
import {
KeplrETCQueries,
Expand Down Expand Up @@ -114,6 +115,7 @@ export class RootStore {
public readonly signInteractionStore: SignInteractionStore;
public readonly signEthereumInteractionStore: SignEthereumInteractionStore;
public readonly signStarknetTxInteractionStore: SignStarknetTxInteractionStore;
public readonly signStarknetMessageInteractionStore: SignStarknetMessageInteractionStore;
public readonly chainSuggestStore: ChainSuggestStore;
public readonly icnsInteractionStore: ICNSInteractionStore;

Expand Down Expand Up @@ -288,6 +290,8 @@ export class RootStore {
this.signStarknetTxInteractionStore = new SignStarknetTxInteractionStore(
this.interactionStore
);
this.signStarknetMessageInteractionStore =
new SignStarknetMessageInteractionStore(this.interactionStore);
this.chainSuggestStore = new ChainSuggestStore(
this.interactionStore,
CommunityChainInfoRepo
Expand Down
29 changes: 29 additions & 0 deletions packages/background/src/keyring-starknet/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
RequestJsonRpcToStarknetMsg,
GetStarknetKeysForEachVaultSettledMsg,
GetStarknetKeyParamsSelectedMsg,
RequestSignStarknetMessage,
} from "./messages";
import { KeyRingStarknetService } from "./service";
import { PermissionInteractiveService } from "../permission-interactive";
Expand Down Expand Up @@ -41,6 +42,11 @@ export const getHandler: (
service,
permissionInteractionService
)(env, msg as RequestSignStarknetTx);
case RequestSignStarknetMessage:
return handleRequestSignStarknetMessage(
service,
permissionInteractionService
)(env, msg as RequestSignStarknetMessage);
case RequestSignStarknetDeployAccountTx:
return handleRequestSignStarknetDeployAccountTx(
service,
Expand Down Expand Up @@ -127,6 +133,29 @@ const handleRequestSignStarknetTx: (
};
};

const handleRequestSignStarknetMessage: (
service: KeyRingStarknetService,
permissionInteractionService: PermissionInteractiveService
) => InternalHandler<RequestSignStarknetMessage> = (
service,
permissionInteractionService
) => {
return async (env, msg) => {
await permissionInteractionService.ensureEnabledForStarknet(
env,
msg.origin
);

return await service.signStarknetMessageSelected(
env,
msg.origin,
msg.chainId,
msg.signer,
msg.message
);
};
};

const handleRequestSignStarknetDeployAccountTx: (
service: KeyRingStarknetService,
permissionInteractionService: PermissionInteractiveService
Expand Down
2 changes: 2 additions & 0 deletions packages/background/src/keyring-starknet/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
RequestJsonRpcToStarknetMsg,
GetStarknetKeysForEachVaultSettledMsg,
GetStarknetKeyParamsSelectedMsg,
RequestSignStarknetMessage,
} from "./messages";
import { ROUTE } from "./constants";
import { getHandler } from "./handler";
Expand All @@ -21,6 +22,7 @@ export function init(
router.registerMessage(GetStarknetKeyMsg);
router.registerMessage(GetStarknetKeysSettledMsg);
router.registerMessage(RequestSignStarknetTx);
router.registerMessage(RequestSignStarknetMessage);
router.registerMessage(RequestSignStarknetDeployAccountTx);
router.registerMessage(RequestJsonRpcToStarknetMsg);
router.registerMessage(GetStarknetKeysForEachVaultSettledMsg);
Expand Down
Loading

0 comments on commit adfc2b1

Please sign in to comment.