Use signature and address for state keys

This commit is contained in:
Justin Starry 2020-04-01 16:35:12 +08:00 committed by Michael Vines
parent 69502cc68e
commit ef7be97540
4 changed files with 63 additions and 45 deletions

View File

@ -29,7 +29,7 @@ function AccountsCard() {
} }
dispatch({ type: ActionType.Input, pubkey }); dispatch({ type: ActionType.Input, pubkey });
fetchAccountInfo(dispatch, idCounter + 1, pubkey, url); fetchAccountInfo(dispatch, address, url);
const inputEl = addressInput.current; const inputEl = addressInput.current;
if (inputEl) { if (inputEl) {

View File

@ -35,7 +35,7 @@ function TransactionsCard() {
} }
dispatch({ type: ActionType.InputSignature, signature }); dispatch({ type: ActionType.InputSignature, signature });
checkTransactionStatus(dispatch, idCounter + 1, signature, url); checkTransactionStatus(dispatch, signature, url);
const inputEl = signatureInput.current; const inputEl = signatureInput.current;
if (inputEl) { if (inputEl) {
@ -141,7 +141,7 @@ const renderTransactionRow = (transaction: Transaction) => {
const confirmationsText = `${transaction.confirmations || "-"}`; const confirmationsText = `${transaction.confirmations || "-"}`;
return ( return (
<tr key={transaction.id}> <tr key={transaction.signature}>
<td> <td>
<span className="badge badge-soft-dark badge-pill"> <span className="badge badge-soft-dark badge-pill">
{transaction.id} {transaction.id}

View File

@ -29,7 +29,7 @@ export interface Account {
details?: Details; details?: Details;
} }
type Accounts = { [id: number]: Account }; type Accounts = { [address: string]: Account };
interface State { interface State {
idCounter: number; idCounter: number;
accounts: Accounts; accounts: Accounts;
@ -42,7 +42,7 @@ export enum ActionType {
interface Update { interface Update {
type: ActionType.Update; type: ActionType.Update;
id: number; address: string;
status: Status; status: Status;
details?: Details; details?: Details;
} }
@ -58,10 +58,12 @@ type Dispatch = (action: Action) => void;
function reducer(state: State, action: Action): State { function reducer(state: State, action: Action): State {
switch (action.type) { switch (action.type) {
case ActionType.Input: { case ActionType.Input: {
const address = action.pubkey.toBase58();
if (!!state.accounts[address]) return state;
const idCounter = state.idCounter + 1; const idCounter = state.idCounter + 1;
const accounts = { const accounts = {
...state.accounts, ...state.accounts,
[idCounter]: { [address]: {
id: idCounter, id: idCounter,
status: Status.Checking, status: Status.Checking,
source: Source.Input, source: Source.Input,
@ -71,7 +73,7 @@ function reducer(state: State, action: Action): State {
return { ...state, accounts, idCounter }; return { ...state, accounts, idCounter };
} }
case ActionType.Update: { case ActionType.Update: {
let account = state.accounts[action.id]; let account = state.accounts[action.address];
if (account) { if (account) {
account = { account = {
...account, ...account,
@ -80,7 +82,7 @@ function reducer(state: State, action: Action): State {
}; };
const accounts = { const accounts = {
...state.accounts, ...state.accounts,
[action.id]: account [action.address]: account
}; };
return { ...state, accounts }; return { ...state, accounts };
} }
@ -90,9 +92,9 @@ function reducer(state: State, action: Action): State {
return state; return state;
} }
function urlPublicKeys(): Array<PublicKey> { function urlAddresses(): Array<string> {
const keys: Array<string> = []; const addresses: Array<string> = [];
return keys return addresses
.concat(findGetParameter("account")?.split(",") || []) .concat(findGetParameter("account")?.split(",") || [])
.concat(findGetParameter("accounts")?.split(",") || []) .concat(findGetParameter("accounts")?.split(",") || [])
.concat(findPathSegment("account")?.split(",") || []) .concat(findPathSegment("account")?.split(",") || [])
@ -100,21 +102,27 @@ function urlPublicKeys(): Array<PublicKey> {
.concat(findGetParameter("address")?.split(",") || []) .concat(findGetParameter("address")?.split(",") || [])
.concat(findGetParameter("addresses")?.split(",") || []) .concat(findGetParameter("addresses")?.split(",") || [])
.concat(findPathSegment("address")?.split(",") || []) .concat(findPathSegment("address")?.split(",") || [])
.concat(findPathSegment("addresses")?.split(",") || []) .concat(findPathSegment("addresses")?.split(",") || []);
.map(key => new PublicKey(key));
} }
function initState(): State { function initState(): State {
let idCounter = 0; let idCounter = 0;
const pubkeys = urlPublicKeys(); const addresses = urlAddresses();
const accounts = pubkeys.reduce((accounts: Accounts, pubkey) => { const accounts = addresses.reduce((accounts: Accounts, address) => {
if (!!accounts[address]) return accounts;
try {
const pubkey = new PublicKey(address);
const id = ++idCounter; const id = ++idCounter;
accounts[id] = { accounts[address] = {
id, id,
status: Status.Checking, status: Status.Checking,
source: Source.Url, source: Source.Url,
pubkey pubkey
}; };
} catch (err) {
// TODO display to user
console.error(err);
}
return accounts; return accounts;
}, {}); }, {});
return { idCounter, accounts }; return { idCounter, accounts };
@ -133,8 +141,8 @@ export function AccountsProvider({ children }: AccountsProviderProps) {
React.useEffect(() => { React.useEffect(() => {
if (status !== ClusterStatus.Connected) return; if (status !== ClusterStatus.Connected) return;
Object.values(state.accounts).forEach(account => { Object.keys(state.accounts).forEach(address => {
fetchAccountInfo(dispatch, account.id, account.pubkey, url); fetchAccountInfo(dispatch, address, url);
}); });
}, [status, url]); // eslint-disable-line react-hooks/exhaustive-deps }, [status, url]); // eslint-disable-line react-hooks/exhaustive-deps
@ -149,20 +157,21 @@ export function AccountsProvider({ children }: AccountsProviderProps) {
export async function fetchAccountInfo( export async function fetchAccountInfo(
dispatch: Dispatch, dispatch: Dispatch,
id: number, address: string,
pubkey: PublicKey,
url: string url: string
) { ) {
dispatch({ dispatch({
type: ActionType.Update, type: ActionType.Update,
status: Status.Checking, status: Status.Checking,
id address
}); });
let status; let status;
let details; let details;
try { try {
const result = await new Connection(url).getAccountInfo(pubkey); const result = await new Connection(url).getAccountInfo(
new PublicKey(address)
);
details = { details = {
space: result.data.length, space: result.data.length,
executable: result.executable, executable: result.executable,
@ -174,7 +183,7 @@ export async function fetchAccountInfo(
console.error("Failed to fetch account info", error); console.error("Failed to fetch account info", error);
status = Status.CheckFailed; status = Status.CheckFailed;
} }
dispatch({ type: ActionType.Update, status, details, id }); dispatch({ type: ActionType.Update, status, details, address });
} }
export function useAccounts() { export function useAccounts() {

View File

@ -27,7 +27,7 @@ export interface Transaction {
signature: TransactionSignature; signature: TransactionSignature;
} }
type Transactions = { [id: number]: Transaction }; type Transactions = { [signature: string]: Transaction };
interface State { interface State {
idCounter: number; idCounter: number;
transactions: Transactions; transactions: Transactions;
@ -40,7 +40,7 @@ export enum ActionType {
interface UpdateStatus { interface UpdateStatus {
type: ActionType.UpdateStatus; type: ActionType.UpdateStatus;
id: number; signature: TransactionSignature;
status: Status; status: Status;
slot?: number; slot?: number;
confirmations?: Confirmations; confirmations?: Confirmations;
@ -57,10 +57,12 @@ type Dispatch = (action: Action) => void;
function reducer(state: State, action: Action): State { function reducer(state: State, action: Action): State {
switch (action.type) { switch (action.type) {
case ActionType.InputSignature: { case ActionType.InputSignature: {
if (!!state.transactions[action.signature]) return state;
const idCounter = state.idCounter + 1; const idCounter = state.idCounter + 1;
const transactions = { const transactions = {
...state.transactions, ...state.transactions,
[idCounter]: { [action.signature]: {
id: idCounter, id: idCounter,
status: Status.Checking, status: Status.Checking,
source: Source.Input, source: Source.Input,
@ -70,7 +72,7 @@ function reducer(state: State, action: Action): State {
return { ...state, transactions, idCounter }; return { ...state, transactions, idCounter };
} }
case ActionType.UpdateStatus: { case ActionType.UpdateStatus: {
let transaction = state.transactions[action.id]; let transaction = state.transactions[action.signature];
if (transaction) { if (transaction) {
transaction = { transaction = {
...transaction, ...transaction,
@ -80,7 +82,7 @@ function reducer(state: State, action: Action): State {
}; };
const transactions = { const transactions = {
...state.transactions, ...state.transactions,
[action.id]: transaction [action.signature]: transaction
}; };
return { ...state, transactions }; return { ...state, transactions };
} }
@ -108,12 +110,13 @@ function initState(): State {
const signatures = urlSignatures(); const signatures = urlSignatures();
const transactions = signatures.reduce( const transactions = signatures.reduce(
(transactions: Transactions, signature) => { (transactions: Transactions, signature) => {
const id = ++idCounter; if (!!transactions[signature]) return transactions;
transactions[id] = { idCounter++;
id, transactions[signature] = {
id: idCounter,
signature,
status: Status.Checking, status: Status.Checking,
source: Source.Url, source: Source.Url
signature
}; };
return transactions; return transactions;
}, },
@ -140,8 +143,8 @@ export function TransactionsProvider({ children }: TransactionsProviderProps) {
createDevTransaction(dispatch, url); createDevTransaction(dispatch, url);
} }
Object.values(state.transactions).forEach(tx => { Object.keys(state.transactions).forEach(signature => {
checkTransactionStatus(dispatch, tx.id, tx.signature, url); checkTransactionStatus(dispatch, signature, url);
}); });
}, [status, url]); // eslint-disable-line react-hooks/exhaustive-deps }, [status, url]); // eslint-disable-line react-hooks/exhaustive-deps
@ -158,11 +161,12 @@ async function createDevTransaction(dispatch: Dispatch, url: string) {
try { try {
const connection = new Connection(url); const connection = new Connection(url);
const signature = await connection.requestAirdrop( const signature = await connection.requestAirdrop(
new PublicKey(0), new PublicKey(1),
1, 1,
"recent" "recent"
); );
dispatch({ type: ActionType.InputSignature, signature }); dispatch({ type: ActionType.InputSignature, signature });
checkTransactionStatus(dispatch, signature, url);
} catch (error) { } catch (error) {
console.error("Failed to create dev transaction", error); console.error("Failed to create dev transaction", error);
} }
@ -170,14 +174,13 @@ async function createDevTransaction(dispatch: Dispatch, url: string) {
export async function checkTransactionStatus( export async function checkTransactionStatus(
dispatch: Dispatch, dispatch: Dispatch,
id: number,
signature: TransactionSignature, signature: TransactionSignature,
url: string url: string
) { ) {
dispatch({ dispatch({
type: ActionType.UpdateStatus, type: ActionType.UpdateStatus,
status: Status.Checking, status: Status.Checking,
id signature
}); });
let status; let status;
@ -206,7 +209,13 @@ export async function checkTransactionStatus(
console.error("Failed to check transaction status", error); console.error("Failed to check transaction status", error);
status = Status.CheckFailed; status = Status.CheckFailed;
} }
dispatch({ type: ActionType.UpdateStatus, status, slot, confirmations, id }); dispatch({
type: ActionType.UpdateStatus,
status,
slot,
confirmations,
signature
});
} }
export function useTransactions() { export function useTransactions() {