From 444124eeed85442c83d892a0cd4a47f32fdac0ee Mon Sep 17 00:00:00 2001 From: soralit Date: Wed, 13 Mar 2024 17:19:46 +0800 Subject: [PATCH 01/16] feat: add sign message API for harware wallet --- src/api/modules/connect/auth.ts | 1 + src/api/modules/sign/sign_auth.ts | 13 ++ .../sign_message/sign_message.background.ts | 53 +++-- src/routes/auth/signMessage.tsx | 220 ++++++++++++++++++ src/tabs/auth.tsx | 2 + src/wallets/hardware/keystone.ts | 22 ++ 6 files changed, 287 insertions(+), 24 deletions(-) create mode 100644 src/routes/auth/signMessage.tsx diff --git a/src/api/modules/connect/auth.ts b/src/api/modules/connect/auth.ts index d4ce5893c..5f2787c3b 100644 --- a/src/api/modules/connect/auth.ts +++ b/src/api/modules/connect/auth.ts @@ -10,6 +10,7 @@ export type AuthType = | "unlock" | "token" | "sign" + | "signMessage" | "signature"; export interface AuthData { diff --git a/src/api/modules/sign/sign_auth.ts b/src/api/modules/sign/sign_auth.ts index e8161049d..3b006fcd0 100644 --- a/src/api/modules/sign/sign_auth.ts +++ b/src/api/modules/sign/sign_auth.ts @@ -72,3 +72,16 @@ export const signAuth = ( }); } ); + +export const signAuthMessage = (dataToSign: Uint8Array) => + new Promise>( + (resolve, reject) => { + // start auth + authenticate({ + type: "signMessage", + data: Buffer.from(dataToSign).toString("base64") + }) + .then((res) => resolve(res)) + .catch((err) => reject(err)); + } + ); diff --git a/src/api/modules/sign_message/sign_message.background.ts b/src/api/modules/sign_message/sign_message.background.ts index 07714101d..aaa14fc9d 100644 --- a/src/api/modules/sign_message/sign_message.background.ts +++ b/src/api/modules/sign_message/sign_message.background.ts @@ -4,11 +4,12 @@ import { getActiveKeyfile } from "~wallets"; import browser from "webextension-polyfill"; import { isArrayBuffer, - isLocalWallet, isNotCancelError, isNumberArray, isSignMessageOptions } from "~utils/assertions"; +import { signAuthMessage } from "../sign/sign_auth"; +import Arweave from "arweave"; const background: ModuleFunction = async ( _, @@ -39,32 +40,36 @@ const background: ModuleFunction = async ( // ensure that the currently selected // wallet is not a local wallet - isLocalWallet(activeWallet); + if (activeWallet.type === "local") { + // get signing key using the jwk + const cryptoKey = await crypto.subtle.importKey( + "jwk", + activeWallet.keyfile, + { + name: "RSA-PSS", + hash: options.hashAlgorithm + }, + false, + ["sign"] + ); - // get signing key using the jwk - const cryptoKey = await crypto.subtle.importKey( - "jwk", - activeWallet.keyfile, - { - name: "RSA-PSS", - hash: options.hashAlgorithm - }, - false, - ["sign"] - ); + // hashing 2 times ensures that the app is not draining the user's wallet + // credits to Arweave.app + const signature = await crypto.subtle.sign( + { name: "RSA-RSS", saltLength: 32 }, + cryptoKey, + hash + ); - // hashing 2 times ensures that the app is not draining the user's wallet - // credits to Arweave.app - const signature = await crypto.subtle.sign( - { name: "RSA-PSS", saltLength: 32 }, - cryptoKey, - hash - ); + // remove wallet from memory + freeDecryptedWallet(activeWallet.keyfile); - // remove wallet from memory - freeDecryptedWallet(activeWallet.keyfile); - - return Array.from(new Uint8Array(signature)); + return Array.from(new Uint8Array(signature)); + } else { + const res = await signAuthMessage(dataToSign); + const sig = Arweave.utils.b64UrlToBuffer(res.data.signature); + return Array.from(sig); + } }; export default background; diff --git a/src/routes/auth/signMessage.tsx b/src/routes/auth/signMessage.tsx new file mode 100644 index 000000000..9f51342ad --- /dev/null +++ b/src/routes/auth/signMessage.tsx @@ -0,0 +1,220 @@ +import { replyToAuthRequest, useAuthParams, useAuthUtils } from "~utils/auth"; +import { + decodeSignature, + messageToUR, + transactionToUR +} from "~wallets/hardware/keystone"; +import { constructTransaction } from "~api/modules/sign/transaction_builder"; +import { formatFiatBalance, formatTokenBalance } from "~tokens/currency"; +import { onMessage, sendMessage } from "@arconnect/webext-bridge"; +import type { DecodedTag } from "~api/modules/sign/tags"; +import type { Tag } from "arweave/web/lib/transaction"; +import type { Chunk } from "~api/modules/sign/chunks"; +import { useEffect, useMemo, useState } from "react"; +import { useScanner } from "@arconnect/keystone-sdk"; +import { useActiveWallet } from "~wallets/hooks"; +import { formatAddress } from "~utils/format"; +import { getArPrice } from "~lib/coingecko"; +import type { UR } from "@ngraveio/bc-ur"; +import { + AmountTitle, + FiatAmount, + Properties, + PropertyName, + PropertyValue, + TagValue, + TransactionProperty +} from "~routes/popup/transaction/[id]"; +import { + Button, + Section, + Spacer, + Text, + useToasts +} from "@arconnect/components"; +import AnimatedQRScanner from "~components/hardware/AnimatedQRScanner"; +import AnimatedQRPlayer from "~components/hardware/AnimatedQRPlayer"; +import type Transaction from "arweave/web/lib/transaction"; +import Wrapper from "~components/auth/Wrapper"; +import Progress from "~components/Progress"; +import browser from "webextension-polyfill"; +import Head from "~components/popup/Head"; + +export default function SignMessage() { + // sign params + const params = useAuthParams<{ + data: string; + }>(); + + // reconstructed transaction + const [dataToSign, setDataToSign] = useState(); + + useEffect(() => { + (async () => { + if (!params?.data) return; + // reset tx + setDataToSign(Buffer.from(params?.data, "base64")); + })(); + }, [params]); + + // get auth utils + const { closeWindow, cancel } = useAuthUtils("signMessage", params?.authID); + + // authorize + async function authorize(data?: any) { + // reply to request + await replyToAuthRequest("signMessage", params.authID, undefined, data); + + // close the window + closeWindow(); + } + + /** + * Hardware wallet logic + */ + + // current wallet + const wallet = useActiveWallet(); + + // current page + const [page, setPage] = useState<"qr" | "scanner">(); + + // load tx UR + const [transactionUR, setTransactionUR] = useState(); + + async function loadTransactionUR() { + if (wallet.type !== "hardware" || !dataToSign) return; + + // load the ur data + const ur = await messageToUR(dataToSign, wallet.xfp); + + setTransactionUR(ur); + } + + // loading + const [loading, setLoading] = useState(false); + + // qr-tx scanner + const scanner = useScanner(async (res) => { + setLoading(true); + + try { + // validation + if (!dataToSign) { + throw new Error("Transaction undefined"); + } + + if (wallet?.type !== "hardware") { + throw new Error("Wallet switched while signing"); + } + + // decode signature + const data = await decodeSignature(res); + + // reply + await authorize(data); + } catch (e) { + // log error + console.error( + `[ArConnect] Error decoding signature from keystone\n${e?.message || e}` + ); + + // reply to request + await replyToAuthRequest( + "signMessage", + params.authID, + "Failed to decode signature from keystone" + ); + + // close the window + closeWindow(); + } + + setLoading(false); + }); + + // toast + const { setToast } = useToasts(); + + if (!params) return <>; + + return ( + +
+ + + {(!page && dataToSign && ( +
+ + + Message + + {Buffer.from(dataToSign).toString("hex")} + + + +
+ )) || ( +
+ {browser.i18n.getMessage("sign_scan_qr")} + + {(page === "qr" && ) || ( + <> + + setToast({ + type: "error", + duration: 2300, + content: browser.i18n.getMessage(`keystone_${error}`) + }) + } + /> + + + {browser.i18n.getMessage( + "keystone_scan_progress", + `${scanner.progress.toFixed(0)}%` + )} + + + + )} +
+ )} +
+
+ {page !== "scanner" && ( + <> + + + + )} + +
+
+ ); +} diff --git a/src/tabs/auth.tsx b/src/tabs/auth.tsx index 2ea1618db..04d054dd9 100644 --- a/src/tabs/auth.tsx +++ b/src/tabs/auth.tsx @@ -14,6 +14,7 @@ import Connect from "~routes/auth/connect"; import Unlock from "~routes/auth/unlock"; import Token from "~routes/auth/token"; import Sign from "~routes/auth/sign"; +import SignMessage from "~routes/auth/signMessage"; export default function Auth() { const theme = useTheme(); @@ -33,6 +34,7 @@ export default function Auth() { + diff --git a/src/wallets/hardware/keystone.ts b/src/wallets/hardware/keystone.ts index 50099c1f3..4458c773a 100644 --- a/src/wallets/hardware/keystone.ts +++ b/src/wallets/hardware/keystone.ts @@ -76,6 +76,28 @@ export async function transactionToUR( return signRequest.toUR(); } +export async function messageToUR( + message: Uint8Array, + xfp: string, + options: SignatureOptions = { saltLength: 32 } +) { + const messageBuff = Buffer.from(message); + + // request ID + const requestID = uuid(); + + // construct request + const signRequest = ArweaveSignRequest.constructArweaveRequest( + messageBuff, + xfp, + SignType.Message, + options.saltLength, + requestID + ); + + return signRequest.toUR(); +} + /** * Decode cbor result from a keystone QR code * with an Arweave transaction From e1442d10cd708466e02bba68a5a85b94c8b8000b Mon Sep 17 00:00:00 2001 From: nicholas ma Date: Thu, 21 Mar 2024 14:13:53 -0700 Subject: [PATCH 02/16] hotfix: added alarminfo to notification handler --- src/notifications/api.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/notifications/api.ts b/src/notifications/api.ts index 0bee0e292..04d39cead 100644 --- a/src/notifications/api.ts +++ b/src/notifications/api.ts @@ -1,7 +1,7 @@ import { ExtensionStorage } from "~utils/storage"; import { getActiveAddress } from "~wallets"; import iconUrl from "url:/assets/icon512.png"; -import browser from "webextension-polyfill"; +import browser, { type Alarms } from "webextension-polyfill"; import { gql } from "~gateways/api"; import { suggestedGateways } from "~gateways/gateway"; import { @@ -43,7 +43,9 @@ export type Transaction = { type ArNotificationsHandlerReturnType = [Transaction[], number, any[]]; -export async function notificationsHandler() { +export async function notificationsHandler(alarmInfo?: Alarms.Alarm) { + if (alarmInfo && !alarmInfo.name.startsWith("notifications")) return; + const notificationSetting: boolean = await ExtensionStorage.get( "setting_notifications" ); From 1c3e6bb1866f04a24b02a40c2e760025f705e951 Mon Sep 17 00:00:00 2001 From: nicholas ma Date: Mon, 25 Mar 2024 15:13:49 -0700 Subject: [PATCH 03/16] fix: wip manual add warp tokens --- .../dashboard/subsettings/AddToken.tsx | 67 +++++++++++++++++-- 1 file changed, 63 insertions(+), 4 deletions(-) diff --git a/src/components/dashboard/subsettings/AddToken.tsx b/src/components/dashboard/subsettings/AddToken.tsx index ee8fc1e66..406b061d7 100644 --- a/src/components/dashboard/subsettings/AddToken.tsx +++ b/src/components/dashboard/subsettings/AddToken.tsx @@ -6,13 +6,17 @@ import { useAo, type TokenInfo, useAoTokens } from "~tokens/aoTokens/ao"; import { getTokenInfo } from "~tokens/aoTokens/router"; import styled from "styled-components"; import { isAddress } from "~utils/assertions"; -import { getAoTokens } from "~tokens"; +import { getAoTokens, getDreForToken } from "~tokens"; import { ExtensionStorage } from "~utils/storage"; import { SubTitle } from "./ContactSettings"; +import { DREContract, DRENode } from "@arconnect/warp-dre"; +import type { TokenState } from "~tokens/token"; export default function AddToken() { const targetInput = useInput(); + const warpInput = useInput(); const [token, setToken] = useState(); + const [type, setType] = useState("ao"); const ao = useAo(); const { setToast } = useToasts(); @@ -46,8 +50,16 @@ export default function AddToken() { try { //TODO double check isAddress(targetInput.state); - const tokenInfo = await getTokenInfo(targetInput.state, ao); - setToken(tokenInfo); + if (type === "ao") { + const tokenInfo = await getTokenInfo(targetInput.state, ao); + setToken(tokenInfo); + } else { + let dre = await getDreForToken(warpInput.state); + console.log("dres", dre); + const contract = new DREContract(warpInput.state, new DRENode(dre)); + const { state } = await contract.getState(); + console.log("state", state); + } } catch (err) { console.log("herr", err); } @@ -55,19 +67,66 @@ export default function AddToken() { fetchTokenInfo(); }, [targetInput.state]); + useEffect(() => { + const fetchTokenInfo = async () => { + try { + //TODO double check + isAddress(warpInput.state); + console.log("add", warpInput.state); + + let dre = await getDreForToken(warpInput.state); + console.log("dres", dre); + const contract = new DREContract(warpInput.state, new DRENode(dre)); + const { state } = await contract.getState(); + console.log("state", state); + // setToken(tokenInfo); + } catch (err) { + console.log("herer", err); + } + }; + fetchTokenInfo(); + }, [warpInput.state]); + return (
{browser.i18n.getMessage("import_token")} + + {type === "warp" && ( + + )} + + {token && ( TICKER: From 09c3a2e83d6f1372741ed0164ec8acdb6f7ca719 Mon Sep 17 00:00:00 2001 From: elehmandevelopment Date: Thu, 28 Mar 2024 11:00:50 -0600 Subject: [PATCH 04/16] refactor: ao token component --- .../dashboard/list/TokenListItem.tsx | 69 ++++++++++++++----- 1 file changed, 50 insertions(+), 19 deletions(-) diff --git a/src/components/dashboard/list/TokenListItem.tsx b/src/components/dashboard/list/TokenListItem.tsx index 9b7dd3dfb..7f3b25076 100644 --- a/src/components/dashboard/list/TokenListItem.tsx +++ b/src/components/dashboard/list/TokenListItem.tsx @@ -59,26 +59,12 @@ export default function TokenListItem({ token, active, ao }: Props) { setImage(viewblock.getTokenLogo(token.id)); } })(); - }, [token, theme, gateway]); + }, [token, theme, gateway, ao]); // router const [, setLocation] = useLocation(); - return ao ? ( - - {formattedAddress} - ao logo -
- } - active={active} - > - - - ) : ( + return ( + {formattedAddress} - {token.type} - + {ao && ao logo} + {!ao && {token.type}} + } active={active} dragControls={dragControls} @@ -102,6 +89,45 @@ export default function TokenListItem({ token, active, ao }: Props) { ); + + // return ao ? ( + // + // {formattedAddress} + // ao logo + // + // } + // active={active} + // > + // + // + // ) : ( + // setLocation(`/tokens/${token.id}`)} + // > + // + // {formattedAddress} + // {token.type} + // + // } + // active={active} + // dragControls={dragControls} + // > + // + // + // + // ); } const Image = styled.img` @@ -111,6 +137,11 @@ const Image = styled.img` border-radius: 2px; `; +const DescriptionWrapper = styled.div` + display: flex; + gap: 8px; +`; + const TokenLogo = styled.img.attrs({ alt: "token-logo", draggable: false From ab3bd4d3ef5edbb026b13256460aac7f192d3ea8 Mon Sep 17 00:00:00 2001 From: nicholas ma Date: Thu, 28 Mar 2024 16:41:45 -0700 Subject: [PATCH 05/16] fix: refresh on ao token load, can manually load warp tokens --- src/components/dashboard/Tokens.tsx | 19 ++- .../dashboard/subsettings/AddToken.tsx | 124 +++++++++++------- src/tokens/aoTokens/ao.ts | 1 + 3 files changed, 88 insertions(+), 56 deletions(-) diff --git a/src/components/dashboard/Tokens.tsx b/src/components/dashboard/Tokens.tsx index eb0ab25ca..8745534a2 100644 --- a/src/components/dashboard/Tokens.tsx +++ b/src/components/dashboard/Tokens.tsx @@ -9,7 +9,7 @@ import styled from "styled-components"; import PermissionCheckbox from "~components/auth/PermissionCheckbox"; import browser from "webextension-polyfill"; import { Button, Label, Spacer, Text } from "@arconnect/components"; -import { useAoTokens } from "~tokens/aoTokens/ao"; +import { type TokenInfoWithBalance } from "~tokens/aoTokens/ao"; export default function Tokens() { // tokens @@ -20,14 +20,19 @@ export default function Tokens() { }, [] ); - - const [aoTokens] = useAoTokens(); + const [aoTokens] = useStorage( + { + key: "ao_tokens", + instance: ExtensionStorage + }, + [] + ); const enhancedAoTokens = useMemo(() => { return aoTokens.map((token) => ({ - id: token.id, + id: token.processId, defaultLogo: token.Logo, - balance: token.balance, + balance: 0, ticker: token.Ticker, type: "asset" as TokenType, name: token.Name @@ -114,7 +119,7 @@ export default function Tokens() { /> ))} - {enhancedAoTokens.length > 0 && ( + {enhancedAoTokens.length > 0 && aoSettingsState && ( <>
diff --git a/src/components/dashboard/subsettings/AddToken.tsx b/src/components/dashboard/subsettings/AddToken.tsx index 406b061d7..e8bcc7021 100644 --- a/src/components/dashboard/subsettings/AddToken.tsx +++ b/src/components/dashboard/subsettings/AddToken.tsx @@ -6,40 +6,53 @@ import { useAo, type TokenInfo, useAoTokens } from "~tokens/aoTokens/ao"; import { getTokenInfo } from "~tokens/aoTokens/router"; import styled from "styled-components"; import { isAddress } from "~utils/assertions"; -import { getAoTokens, getDreForToken } from "~tokens"; +import { addToken, getAoTokens, getDreForToken } from "~tokens"; import { ExtensionStorage } from "~utils/storage"; import { SubTitle } from "./ContactSettings"; import { DREContract, DRENode } from "@arconnect/warp-dre"; -import type { TokenState } from "~tokens/token"; +import type { TokenState, TokenType } from "~tokens/token"; +import { concatGatewayURL } from "~gateways/utils"; +import { useGateway } from "~gateways/wayfinder"; export default function AddToken() { const targetInput = useInput(); - const warpInput = useInput(); + const gateway = useGateway({ startBlock: 0 }); + const [tokenType, setTokenType] = useState("asset"); const [token, setToken] = useState(); const [type, setType] = useState("ao"); + const [warp, setWarp] = useState(null); const ao = useAo(); const { setToast } = useToasts(); const onImportToken = async () => { try { - const tokens = await getAoTokens(); + if (type === "ao") { + const tokens = await getAoTokens(); - if (tokens.find((token) => token.processId === targetInput.state)) { + if (tokens.find((token) => token.processId === targetInput.state)) { + setToast({ + type: "error", + content: browser.i18n.getMessage("token_already_added"), + duration: 3000 + }); + throw new Error("Token already added"); + } + + tokens.push({ ...token, processId: targetInput.state }); + await ExtensionStorage.set("ao_tokens", tokens); + setToast({ + type: "success", + content: browser.i18n.getMessage("token_imported"), + duration: 3000 + }); + } else if (warp && type === "warp") { + await addToken(targetInput.state, tokenType, warp); setToast({ - type: "error", - content: browser.i18n.getMessage("token_already_added"), + type: "success", + content: browser.i18n.getMessage("token_imported"), duration: 3000 }); - throw new Error("Token already added"); } - - tokens.push({ ...token, processId: targetInput.state }); - await ExtensionStorage.set("ao_tokens", tokens); - setToast({ - type: "success", - content: browser.i18n.getMessage("token_imported"), - duration: 3000 - }); } catch (err) { console.log("err", err); } @@ -54,38 +67,23 @@ export default function AddToken() { const tokenInfo = await getTokenInfo(targetInput.state, ao); setToken(tokenInfo); } else { - let dre = await getDreForToken(warpInput.state); - console.log("dres", dre); - const contract = new DREContract(warpInput.state, new DRENode(dre)); + let dre = await getDreForToken(targetInput.state); + const contract = new DREContract(targetInput.state, new DRENode(dre)); const { state } = await contract.getState(); - console.log("state", state); + const values: TokenInfo = { + Name: state.name, + Ticker: state.ticker, + Denomination: 0 + }; + setWarp(dre); + setToken(values); } } catch (err) { console.log("herr", err); } }; fetchTokenInfo(); - }, [targetInput.state]); - - useEffect(() => { - const fetchTokenInfo = async () => { - try { - //TODO double check - isAddress(warpInput.state); - console.log("add", warpInput.state); - - let dre = await getDreForToken(warpInput.state); - console.log("dres", dre); - const contract = new DREContract(warpInput.state, new DRENode(dre)); - const { state } = await contract.getState(); - console.log("state", state); - // setToken(tokenInfo); - } catch (err) { - console.log("herer", err); - } - }; - fetchTokenInfo(); - }, [warpInput.state]); + }, [targetInput.state, tokenType, token]); return ( @@ -97,6 +95,7 @@ export default function AddToken() { onChange={(e) => { // @ts-expect-error setType(e.target.value); + setTokenType("asset"); }} fullWidth > @@ -108,14 +107,27 @@ export default function AddToken() { {type === "warp" && ( - + <> + + + )} @@ -133,6 +145,11 @@ export default function AddToken() { {token.Ticker} NAME: {token.Name} + {tokenType === "collectible" && ( + + )} )} @@ -143,6 +160,15 @@ export default function AddToken() { ); } +const Image = styled.div<{ src: string }>` + position: relative; + background-image: url(${(props) => props.src}); + background-size: cover; + background-position: center; + padding-top: 100%; + border-radius: 12px; +`; + const Title = styled(Text).attrs({ title: true, noMargin: true diff --git a/src/tokens/aoTokens/ao.ts b/src/tokens/aoTokens/ao.ts index a09868806..d1f402df2 100644 --- a/src/tokens/aoTokens/ao.ts +++ b/src/tokens/aoTokens/ao.ts @@ -253,6 +253,7 @@ export interface TokenInfo { Ticker?: string; Logo?: string; Denomination: number; + processId?: string; } export interface TokenInfoWithBalance extends TokenInfo { id: string; From 0a9cf3c2439c81ac0aa390738d9870db601e1d6b Mon Sep 17 00:00:00 2001 From: Marton Lederer Date: Fri, 29 Mar 2024 15:20:51 +0100 Subject: [PATCH 06/16] feat: separate message component --- src/components/auth/Message.tsx | 84 +++++++++++++++++++++++++++++++++ src/routes/auth/signature.tsx | 76 ++--------------------------- 2 files changed, 88 insertions(+), 72 deletions(-) create mode 100644 src/components/auth/Message.tsx diff --git a/src/components/auth/Message.tsx b/src/components/auth/Message.tsx new file mode 100644 index 000000000..56894d422 --- /dev/null +++ b/src/components/auth/Message.tsx @@ -0,0 +1,84 @@ +import { Card, Spacer, Text } from "@arconnect/components"; +import browser from "webextension-polyfill"; +import { useMemo, useState } from "react"; +import styled from "styled-components"; + +export default function Message({ message }: Props) { + // message decode type + const [decodeType, setDecodeType] = useState("UTF-8"); + const availableDecodeTypes = [ + "utf-8", + "hex", + "ibm866", + "mac", + "windows-1251", + "gbk", + "utf-16" + ]; + + // current message + const msg = useMemo(() => { + if (typeof message === "undefined") return ""; + const messageBytes = new Uint8Array(message); + + // handle hex + if (decodeType === "hex") { + return [...new Uint8Array(messageBytes.buffer)] + .map((v) => "0x" + v.toString(16).padStart(2, "0")) + .join(" "); + } + + // handle other types + return new TextDecoder(decodeType).decode(messageBytes); + }, [message, decodeType]); + + return ( + <> + + {browser.i18n.getMessage("signature_message")} + setDecodeType(e.target.value)}> + {availableDecodeTypes.map((type, i) => ( + + ))} + + + + + {msg} + + + ); +} + +interface Props { + message?: number[]; +} + +const MessageHeader = styled.div` + display: flex; + align-items: center; + justify-content: space-between; + + p, + select { + font-size: 0.95rem; + } +`; + +const EncodingSelect = styled.select` + font-weight: 500; + color: rgb(${(props) => props.theme.secondaryText}); + outline: none; + border: none; + padding: 0; + margin: 0; + background-color: transparent; +`; + +const MessageText = styled(Text).attrs({ + noMargin: true +})` + font-size: 0.9rem; +`; diff --git a/src/routes/auth/signature.tsx b/src/routes/auth/signature.tsx index 98c26bde5..acce5ef7d 100644 --- a/src/routes/auth/signature.tsx +++ b/src/routes/auth/signature.tsx @@ -1,10 +1,10 @@ import { replyToAuthRequest, useAuthParams, useAuthUtils } from "~utils/auth"; -import { Button, Card, Section, Spacer, Text } from "@arconnect/components"; -import { useEffect, useMemo, useState } from "react"; +import { Button, Section, Spacer, Text } from "@arconnect/components"; +import Message from "~components/auth/Message"; import Wrapper from "~components/auth/Wrapper"; import browser from "webextension-polyfill"; import Head from "~components/popup/Head"; -import styled from "styled-components"; +import { useEffect } from "react"; export default function Signature() { // connect params @@ -37,34 +37,6 @@ export default function Signature() { closeWindow(); } - // message decode type - const [decodeType, setDecodeType] = useState("UTF-8"); - const availableDecodeTypes = [ - "utf-8", - "hex", - "ibm866", - "mac", - "windows-1251", - "gbk", - "utf-16" - ]; - - // current message - const message = useMemo(() => { - if (typeof params?.message === "undefined") return ""; - const messageBytes = new Uint8Array(params.message); - - // handle hex - if (decodeType === "hex") { - return [...new Uint8Array(messageBytes.buffer)] - .map((v) => "0x" + v.toString(16).padStart(2, "0")) - .join(" "); - } - - // handle other types - return new TextDecoder(decodeType).decode(messageBytes); - }, [params?.message, decodeType]); - return (
@@ -81,20 +53,7 @@ export default function Signature() {
- - {browser.i18n.getMessage("signature_message")} - setDecodeType(e.target.value)}> - {availableDecodeTypes.map((type, i) => ( - - ))} - - - - - {message} - + From cdae74efb852cb650aafa988f5fb7508b258497e Mon Sep 17 00:00:00 2001 From: nicholas ma Date: Mon, 1 Apr 2024 18:46:03 -0700 Subject: [PATCH 16/16] chore: version bump for beta --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3bbd9ab86..0858dd05c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "arconnect", "displayName": "ArConnect", - "version": "1.7.0", + "version": "1.7.1", "description": "__MSG_extensionDescription__", "author": "th8ta", "packageManager": "yarn@1.22.18",