Skip to content
This repository has been archived by the owner on Dec 7, 2023. It is now read-only.

Commit

Permalink
Now supporting the import of external accounts
Browse files Browse the repository at this point in the history
  • Loading branch information
kpachhai committed Sep 27, 2023
1 parent 013526a commit 7304274
Show file tree
Hide file tree
Showing 20 changed files with 495 additions and 143 deletions.
6 changes: 4 additions & 2 deletions packages/site/src/components/cards/GetAccountInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import {
} from '../../utils';
import { hederaNetworks } from '../../utils/hedera';
import { Card, SendHelloButton } from '../base';
import { GetExternalAccountRef } from '../sections/ExternalAccount';
import ExternalAccount, {
GetExternalAccountRef,
} from '../sections/ExternalAccount';

type Props = {
setCurrentNetwork: React.Dispatch<React.SetStateAction<string>>;
Expand Down Expand Up @@ -70,7 +72,7 @@ const GetAccountInfo: FC<Props> = ({
description: 'Get the current account information',
form: (
<>
{/* <ExternalAccount ref={externalAccountRef} /> */}
<ExternalAccount ref={externalAccountRef} />
<label>
Enter an account Id
<input
Expand Down
1 change: 1 addition & 0 deletions packages/site/src/components/cards/SendHelloMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const SendHelloHessage: FC<Props> = ({
const network = hederaNetworks.get('testnet') as string;
setCurrentNetwork(network);
const metamaskAddress = await getCurrentMetamaskAccount();
console.log('address: ', metamaskAddress);
setMetamaskAddress(metamaskAddress);

const response: any = await sendHello(network);
Expand Down
30 changes: 18 additions & 12 deletions packages/site/src/components/sections/ExternalAccount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ export type GetExternalAccountRef = {

const ExternalAccount = forwardRef(({}, ref: Ref<GetExternalAccountRef>) => {
const [externalAccount, setExternalAccount] = useState(false);
const [accountId, setAccountId] = useState('');
const [accountIdOrEvmAddress, setAccountIdOrEvmAddress] = useState('');

useImperativeHandle(ref, () => ({
handleGetAccountParams() {
let params;
if (externalAccount) {
params = {
externalAccount: {
accountId,
accountIdOrEvmAddress,
},
};
}
Expand All @@ -25,7 +25,7 @@ const ExternalAccount = forwardRef(({}, ref: Ref<GetExternalAccountRef>) => {
}));

return (
<>
<div>
<Form>
<Form.Check
type="checkbox"
Expand All @@ -35,16 +35,22 @@ const ExternalAccount = forwardRef(({}, ref: Ref<GetExternalAccountRef>) => {
setExternalAccount(e.target.checked);
}}
/>
<Form.Label>Account Id</Form.Label>
<Form.Control
size="lg"
type="text"
placeholder="Account Id"
style={{ marginBottom: 8 }}
onChange={(e) => setAccountId(e.target.value)}
/>
{externalAccount && (
<>
<Form.Label>
Enter your Account Id or EVM address to connect to
</Form.Label>
<Form.Control
size="lg"
type="text"
placeholder="Account Id or EVM address"
style={{ marginBottom: 8 }}
onChange={(e) => setAccountIdOrEvmAddress(e.target.value)}
/>
</>
)}
</Form>
</>
</div>
);
});

Expand Down
10 changes: 8 additions & 2 deletions packages/site/src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,14 @@ const Index = () => {
<dd>{currentNetwork ? 'Connected' : 'Disconnected'}</dd>
<dt>Current Network:</dt>
<dd>{currentNetwork}</dd>
<dt>Currently Connected Metamask Account: </dt>
<dd>{metamaskAddress}</dd>
<dt>Currently Connected Account Type: </dt>
<dd>
{metamaskAddress === accountInfo?.metamaskAddress
? 'Metamask Account'
: 'Non-Metamask Account'}
</dd>
<dt>Currently Connected Address: </dt>
<dd>{accountInfo?.metamaskAddress}</dd>
<dt>Hedera Account ID: </dt>
<dd>{accountInfo?.hederaAccountId}</dd>
<dt>Hedera EVM Address: </dt>
Expand Down
29 changes: 15 additions & 14 deletions packages/site/src/types/snap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,33 @@ export type Snap = {
initialPermissions: Record<string, unknown>;
};

export type Account = {
metamaskAddress: string;
hederaAccountId: string;
hederaEvmAddress: string;
balance: AccountBalance;
network: string;
export type TokenBalance = {
// balance has already had decimals applied
balance: number;
decimals: number;
};

export type AccountBalance = {
// balance here in hbars
hbars: number;
timestamp: string;
tokens: Map<string, TokenBalance>; // Map of TOKEN -> decimals
};

export type TokenBalance = {
// balance has already had decimals applied
balance: number;
decimals: number;
export type Account = {
metamaskAddress: string;
hederaAccountId: string;
hederaEvmAddress: string;
balance: AccountBalance;
network: string;
};

export type SimpleTransfer = {
// HBAR or Token ID (as string)
asset?: string;
to?: string;
asset: string;
to: string;
// amount must be in low denom
amount?: number;
amount: number;
};

export type TransferCryptoRequestParams = {
Expand All @@ -43,6 +44,6 @@ export type TransferCryptoRequestParams = {

export type ExternalAccountParams = {
externalAccount: {
accountId: string;
accountIdOrEvmAddress: string;
};
};
2 changes: 1 addition & 1 deletion packages/snap/snap.manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"url": "https://github.com/tuum-tech/hedera-pulse.git"
},
"source": {
"shasum": "+GQraBauxdm43Ba4RQf0FFrA59AzXZeNalbkYslzVMg=",
"shasum": "zPnXj8v/itQVsoTFa5vgxROTDDJheMBC2yfhDx9qDss=",
"location": {
"npm": {
"filePath": "dist/snap.js",
Expand Down
12 changes: 9 additions & 3 deletions packages/snap/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { getSnapStateUnchecked } from './snap/state';
import { PulseSnapParams } from './types/state';
import { init } from './utils/init';
import {
isExternalAccountFlagSet,
isValidGetAccountInfoRequest,
isValidTransferCryptoParams,
} from './utils/params';
Expand All @@ -36,9 +37,9 @@ export const onRpcRequest: OnRpcRequestHandler = async ({
JSON.stringify(request.params, null, 4),
);

let state = await getSnapStateUnchecked(snap);
let state = await getSnapStateUnchecked();
if (state === null || _.isEmpty(state)) {
state = await init(origin, snap);
state = await init(origin);
}
console.log(
'state:',
Expand All @@ -49,7 +50,12 @@ export const onRpcRequest: OnRpcRequestHandler = async ({
),
);

await setCurrentAccount(origin, state, request.params);
let isExternalAccount = false;
if (isExternalAccountFlagSet(request.params)) {
isExternalAccount = true;
}

await setCurrentAccount(origin, state, request.params, isExternalAccount);
console.log(
`Current account: ${JSON.stringify(state.currentAccount, null, 4)}`,
);
Expand Down
3 changes: 2 additions & 1 deletion packages/snap/src/rpc/account/getAccountBalance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export async function getAccountBalance(

try {
const hederaClient = await createHederaClient(
state.accountState[metamaskAddress].keyStore.curve,
state.accountState[metamaskAddress].keyStore.privateKey,
hederaAccountId,
network,
Expand All @@ -28,7 +29,7 @@ export async function getAccountBalance(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
state.accountState[metamaskAddress].accountInfo.balance!.timestamp =
new Date().toISOString();
await updateSnapState(snap, state);
await updateSnapState(state);
} catch (error: any) {
console.error(
`Error while trying to get account balance: ${String(error)}`,
Expand Down
12 changes: 11 additions & 1 deletion packages/snap/src/rpc/account/getAccountInfo.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { AccountId } from '@hashgraph/sdk';
import { AccountInfoJson } from '@hashgraph/sdk/lib/account/AccountInfo';
import _ from 'lodash';
import { createHederaClient } from '../../snap/account';
Expand All @@ -23,12 +24,21 @@ export async function getAccountInfo(

try {
const hederaClient = await createHederaClient(
state.accountState[metamaskAddress].keyStore.curve,
state.accountState[metamaskAddress].keyStore.privateKey,
hederaAccountId,
network,
);

if (accountId && !_.isEmpty(accountId)) {
if (!AccountId.fromString(accountId)) {
console.error(
`Invalid Hedera Account Id '${accountId}' is not a valid account Id`,
);
throw new Error(
`Invalid Hedera Account Id '${accountId}' is not a valid account Id`,
);
}
accountInfo = await hederaClient.getAccountInfo(accountId);
} else {
accountInfo = await hederaClient.getAccountInfo(hederaAccountId);
Expand All @@ -42,7 +52,7 @@ export async function getAccountInfo(
new Date().toISOString();

state.accountState[metamaskAddress].accountInfo.extraData = accountInfo;
await updateSnapState(snap, state);
await updateSnapState(state);
}
} catch (error: any) {
console.error(`Error while trying to get account info: ${String(error)}`);
Expand Down
1 change: 1 addition & 0 deletions packages/snap/src/rpc/account/transferCrypto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export async function transferCrypto(
}

const hederaClient = await createHederaClient(
state.accountState[metamaskAddress].keyStore.curve,
state.accountState[metamaskAddress].keyStore.privateKey,
hederaAccountId,
network,
Expand Down
15 changes: 13 additions & 2 deletions packages/snap/src/services/impl/hedera/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,10 @@ export class HederaServiceImpl implements HederaService {
} else if (this.network === 'previewnet') {
client = Client.forPreviewnet();
} else {
client = Client.forMainnet();
// client = Client.forMainnet();
client = Client.forNetwork({
'https://node01-00-grpc.swirlds.com:443': new AccountId(4),
});
}

// NOTE: important, ensure that we pre-compute the health state of all nodes
Expand Down Expand Up @@ -175,6 +178,7 @@ 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 ||
Expand Down Expand Up @@ -202,17 +206,24 @@ async function testClientOperatorMatch(client: Client) {
/**
* To HederaAccountInfo.
*
* @param _curve - Curve that was used to derive the keys('ECDSA_SECP256K1' | 'ED25519').
* @param _privateKey - Private Key.
* @param _accountId - Account Id.
* @param _network - Network.
*/
export async function getHederaClient(
_curve: string,
_privateKey: string,
_accountId: string,
_network: string,
): Promise<SimpleHederaClient | null> {
const accountId = AccountId.fromString(_accountId);
const privateKey = PrivateKey.fromStringECDSA(_privateKey);

let privateKey = PrivateKey.fromStringECDSA(_privateKey);
if (_curve === 'ED25519') {
privateKey = PrivateKey.fromStringED25519(_privateKey);
}

const wallet: Wallet = new PrivateKeySoftwareWallet(privateKey);
const hederaService = new HederaServiceImpl(_network);

Expand Down
Loading

0 comments on commit 7304274

Please sign in to comment.