From 34421943cc087ea3e9a4e5eef74c8eb1526e035c Mon Sep 17 00:00:00 2001 From: Kiran Pachhai Date: Wed, 27 Sep 2023 13:27:59 -0400 Subject: [PATCH] Handling the curve from the frontend on external accounts --- packages/site/src/components/base/Card.tsx | 2 +- .../src/components/cards/GetAccountInfo.tsx | 3 +- .../components/sections/ExternalAccount.tsx | 17 +++++- packages/site/src/config/styles.ts | 4 +- packages/site/src/types/snap.ts | 1 + packages/snap/snap.manifest.json | 2 +- .../snap/src/services/impl/hedera/index.ts | 1 - packages/snap/src/snap/account.ts | 53 +++++++++++++++---- packages/snap/src/types/account.ts | 1 + packages/snap/src/utils/params.ts | 17 ++++++ 10 files changed, 85 insertions(+), 16 deletions(-) diff --git a/packages/site/src/components/base/Card.tsx b/packages/site/src/components/base/Card.tsx index 3f3bd57..46cf0ce 100644 --- a/packages/site/src/components/base/Card.tsx +++ b/packages/site/src/components/base/Card.tsx @@ -18,7 +18,7 @@ const CardWrapper = styled.div<{ }>` display: flex; flex-direction: column; - width: ${({ fullWidth }) => (fullWidth ? '100%' : '250px')}; + width: ${({ fullWidth }) => (fullWidth ? '100%' : '640px')}; background-color: ${({ theme }) => theme.colors.card.default}; margin-top: 2.4rem; margin-bottom: 2.4rem; diff --git a/packages/site/src/components/cards/GetAccountInfo.tsx b/packages/site/src/components/cards/GetAccountInfo.tsx index 8ffaa43..67924f8 100644 --- a/packages/site/src/components/cards/GetAccountInfo.tsx +++ b/packages/site/src/components/cards/GetAccountInfo.tsx @@ -37,7 +37,7 @@ const GetAccountInfo: FC = ({ const handleGetAccountInfoClick = async () => { setLoading(true); try { - const network = hederaNetworks.get('testnet') as string; + const network = hederaNetworks.get('mainnet') as string; setCurrentNetwork(network); const metamaskAddress = await getCurrentMetamaskAccount(); setMetamaskAddress(metamaskAddress); @@ -83,6 +83,7 @@ const GetAccountInfo: FC = ({ onChange={(e) => setAccountId(e.target.value)} /> +
), button: ( diff --git a/packages/site/src/components/sections/ExternalAccount.tsx b/packages/site/src/components/sections/ExternalAccount.tsx index 4d11696..3929889 100644 --- a/packages/site/src/components/sections/ExternalAccount.tsx +++ b/packages/site/src/components/sections/ExternalAccount.tsx @@ -9,16 +9,20 @@ export type GetExternalAccountRef = { const ExternalAccount = forwardRef(({}, ref: Ref) => { const [externalAccount, setExternalAccount] = useState(false); const [accountIdOrEvmAddress, setAccountIdOrEvmAddress] = useState(''); + const [curve, setCurve] = useState(''); useImperativeHandle(ref, () => ({ handleGetAccountParams() { - let params; + let params = {} as ExternalAccountParams; if (externalAccount) { params = { externalAccount: { accountIdOrEvmAddress, }, }; + if (curve) { + params.externalAccount.curve = curve as 'ECDSA_SECP256K1' | 'ED25519'; + } } return params; }, @@ -47,6 +51,17 @@ const ExternalAccount = forwardRef(({}, ref: Ref) => { style={{ marginBottom: 8 }} onChange={(e) => setAccountIdOrEvmAddress(e.target.value)} /> + + Enter the type of Elliptic Curve to use(default value: + 'ECDSA_SECP256K1'). + + setCurve(e.target.value)} + /> )} diff --git a/packages/site/src/config/styles.ts b/packages/site/src/config/styles.ts index 0c663c9..8594854 100644 --- a/packages/site/src/config/styles.ts +++ b/packages/site/src/config/styles.ts @@ -41,11 +41,11 @@ export const CardContainer = styled.div` flex-direction: row; flex-wrap: wrap; justify-content: space-between; - max-width: 125rem; + max-width: 130rem; width: 100%; height: 100%; margin-top: 1.5rem; - gap: 16px; + gap: 5px; `; export const Notice = styled.div` diff --git a/packages/site/src/types/snap.ts b/packages/site/src/types/snap.ts index dd7ca36..9a5b7a0 100644 --- a/packages/site/src/types/snap.ts +++ b/packages/site/src/types/snap.ts @@ -45,5 +45,6 @@ export type TransferCryptoRequestParams = { export type ExternalAccountParams = { externalAccount: { accountIdOrEvmAddress: string; + curve?: 'ECDSA_SECP256K1' | 'ED25519'; }; }; diff --git a/packages/snap/snap.manifest.json b/packages/snap/snap.manifest.json index e937600..5565db3 100644 --- a/packages/snap/snap.manifest.json +++ b/packages/snap/snap.manifest.json @@ -7,7 +7,7 @@ "url": "https://github.com/tuum-tech/hedera-pulse.git" }, "source": { - "shasum": "zPnXj8v/itQVsoTFa5vgxROTDDJheMBC2yfhDx9qDss=", + "shasum": "1A+2bB0yYSwcwHPBiI4U3AmFvE68tBwTVxGoqsH9R6g=", "location": { "npm": { "filePath": "dist/snap.js", diff --git a/packages/snap/src/services/impl/hedera/index.ts b/packages/snap/src/services/impl/hedera/index.ts index 1b88fcc..2c53fb0 100644 --- a/packages/snap/src/services/impl/hedera/index.ts +++ b/packages/snap/src/services/impl/hedera/index.ts @@ -178,7 +178,6 @@ async function testClientOperatorMatch(client: Client) { try { await tx.execute(client); } catch (error: any) { - console.log('error: ', String(error)); if (error instanceof StatusError) { if ( error.status === Status.InsufficientTxFee || diff --git a/packages/snap/src/snap/account.ts b/packages/snap/src/snap/account.ts index 5969bd2..e27830c 100644 --- a/packages/snap/src/snap/account.ts +++ b/packages/snap/src/snap/account.ts @@ -80,12 +80,23 @@ export async function setCurrentAccount( // Handle external account(non-metamask account) if (isExternalAccount) { const nonMetamaskAccount = params as ExternalAccount; - const { accountIdOrEvmAddress } = nonMetamaskAccount.externalAccount; + const { accountIdOrEvmAddress, curve = 'ECDSA_SECP256K1' } = + nonMetamaskAccount.externalAccount; if (ethers.isAddress(accountIdOrEvmAddress)) { + if (curve !== 'ECDSA_SECP256K1') { + console.error( + `You must use 'ECDSA_SECP256K1' as the curve if you want to import an EVM address. Please make sure to pass in the correct value for "curve".`, + ); + throw new Error( + `You must use 'ECDSA_SECP256K1' as the curve if you want to import an EVM address. Please make sure to pass in the correct value for "curve".`, + ); + } + const { connectedAddress: _connectedAddress, keyStore: _keyStore } = await connectEVMAccount( origin, state, + curve, ensure0xPrefix(accountIdOrEvmAddress), ); connectedAddress = _connectedAddress; @@ -97,6 +108,7 @@ export async function setCurrentAccount( origin, state, network, + curve, (accountIdOrEvmAddress as string).toLowerCase(), ); connectedAddress = _connectedAddress; @@ -149,11 +161,13 @@ export async function setCurrentAccount( * * @param origin - Source. * @param state - Pulse state. + * @param curve - Public Key curve('ECDSA_SECP256K1' | 'ED25519'). * @param evmAddress - EVM Account address. */ async function connectEVMAccount( origin: string, state: PulseSnapState, + curve: 'ECDSA_SECP256K1' | 'ED25519', evmAddress: string, ): Promise { let result = {} as KeyStore; @@ -197,7 +211,7 @@ async function connectEVMAccount( `The private key you passed was invalid for the EVM address '${evmAddress}'. Please try again.`, ); } - result.curve = 'ECDSA_SECP256K1'; + result.curve = curve; result.privateKey = privateKey; result.publicKey = wallet.signingKey.publicKey; result.address = ensure0xPrefix(wallet.address); @@ -224,12 +238,14 @@ async function connectEVMAccount( * @param origin - Source. * @param state - Pulse state. * @param network - Hedera network. + * @param curve - Public Key curve('ECDSA_SECP256K1' | 'ED25519'). * @param accountId - Hedera Account id. */ async function connectHederaAccount( origin: string, state: PulseSnapState, network: string, + curve: 'ECDSA_SECP256K1' | 'ED25519', accountId: string, ): Promise { let result = {} as KeyStore; @@ -268,7 +284,7 @@ async function connectHederaAccount( content: await generateCommonPanel(origin, [ heading('Hedera Account Status'), text( - `This Hedera account is not yet active on ${network}. Please activate it by sending some HBAR to this account.`, + `This Hedera account is not yet active on ${network}. Please activate it by sending some HBAR to this account on '${network}'.`, ), divider(), text(`Public Key: ${publicKey}`), @@ -278,14 +294,24 @@ async function connectHederaAccount( await snapDialog(dialogParamsForHederaAccountId); console.error( - `This Hedera account is not yet active. Please activate it by sending some HBAR to this account. Public Key: ${publicKey}`, + `This Hedera account is not yet active. Please activate it by sending some HBAR to this account on '${network}'. Public Key: ${publicKey}`, ); throw new Error( - `This Hedera account is not yet active. Please activate it by sending some HBAR to this account. Public Key: ${publicKey}`, + `This Hedera account is not yet active. Please activate it by sending some HBAR to this account on '${network}'. Public Key: ${publicKey}`, ); } + + if (accountInfo.key._type !== curve) { + console.error( + `You passed '${curve}' as the digital signature algorithm to use but the account '${accountId}' was derived using '${accountInfo.key._type}' on '${network}'. Please make sure to pass in the correct value for "curve".`, + ); + throw new Error( + `You passed '${curve}' as the digital signature algorithm to use but the account '${accountId}' was derived using '${accountInfo.key._type}' on '${network}'. Please make sure to pass in the correct value for "curve".`, + ); + } + const hederaClient = await getHederaClient( - accountInfo.key._type, + curve, privateKey, accountId, network, @@ -294,7 +320,7 @@ async function connectHederaAccount( result.privateKey = hederaClient ?.getPrivateKey() ?.toStringRaw() as string; - result.curve = accountInfo.key._type as 'ECDSA_SECP256K1' | 'ED25519'; + result.curve = curve; result.publicKey = hederaClient.getPublicKey().toStringRaw(); result.hederaAccountId = accountId; result.address = ensure0xPrefix(accountInfo.evm_address); @@ -323,14 +349,23 @@ async function connectHederaAccount( } } catch (error: any) { console.error( - 'Error while trying to setup a Hedera client. Please try again.', + `Could not setup a Hedera client. Please try again: ${String(error)}`, ); throw new Error( - 'Error while trying to setup a Hedera client. Please try again.', + `Could not setup a Hedera client. Please try again: ${String(error)}`, ); } } + if (state.accountState[connectedAddress].keyStore.curve !== curve) { + console.error( + `You passed '${curve}' as the digital signature algorithm to use but the account '${accountId}' was derived using '${state.accountState[connectedAddress].keyStore.curve}' on '${network}'. Please make sure to pass in the correct value for "curve".`, + ); + throw new Error( + `You passed '${curve}' as the digital signature algorithm to use but the account '${accountId}' was derived using '${state.accountState[connectedAddress].keyStore.curve}' on '${network}'. Please make sure to pass in the correct value for "curve".`, + ); + } + return { connectedAddress, keyStore: result, diff --git a/packages/snap/src/types/account.ts b/packages/snap/src/types/account.ts index ee5ce4c..5d63636 100644 --- a/packages/snap/src/types/account.ts +++ b/packages/snap/src/types/account.ts @@ -4,6 +4,7 @@ import { AccountBalance } from '../services/hedera'; export type ExternalAccount = { externalAccount: { accountIdOrEvmAddress: string; + curve?: 'ECDSA_SECP256K1' | 'ED25519'; }; }; diff --git a/packages/snap/src/utils/params.ts b/packages/snap/src/utils/params.ts index db13ff2..6c7e598 100644 --- a/packages/snap/src/utils/params.ts +++ b/packages/snap/src/utils/params.ts @@ -34,6 +34,23 @@ export function isExternalAccountFlagSet(params: unknown): boolean { 'Invalid externalAccount Params passed. "accountIdOrEvmAddress" must not be empty', ); } + if ( + 'curve' in parameter.externalAccount && + parameter.externalAccount.curve !== null + ) { + if ( + typeof parameter.externalAccount.curve !== 'string' || + (parameter.externalAccount.curve !== 'ECDSA_SECP256K1' && + parameter.externalAccount.curve !== 'ED25519') + ) { + console.error( + 'Invalid externalAccount Params passed. "curve" must be a string and must be either "ECDSA_SECP256K1" or "ED25519"', + ); + throw new Error( + 'Invalid externalAccount Params passed. "curve" must be a string and must be either "ECDSA_SECP256K1" or "ED25519"', + ); + } + } return true; } }