diff --git a/explorer/package-lock.json b/explorer/package-lock.json
index 439bc0d057..bd13f5ad4d 100644
--- a/explorer/package-lock.json
+++ b/explorer/package-lock.json
@@ -1269,9 +1269,9 @@
"integrity": "sha512-DetpxZw1fzPD5xUBrIAoplLChO2VB8DlL5Gg+I1IR9b2wPqYIca2WSUxL5g1vLeR4MsQq1NeWriXAVffV+U1Fw=="
},
"@solana/web3.js": {
- "version": "0.49.4",
- "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-0.49.4.tgz",
- "integrity": "sha512-9mV4MXSzUtBNbtNM5CvgtpPBlLpBlJKAfE4PlwchNA/H6MDWF8ts/MCH4pMbtAr1ZIvdxpsAKqCEUXrsj0ScMA==",
+ "version": "0.51.0",
+ "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-0.51.0.tgz",
+ "integrity": "sha512-mt2JF9QcpL/K2/LSHgj/yqSQXxvCNkLknfvmDClLeI2VbtYMypGcw4tU4C2GrdTzKRUdzM8ncaGONxLJKgFsTQ==",
"requires": {
"@babel/runtime": "^7.3.1",
"bn.js": "^5.0.0",
@@ -1291,9 +1291,9 @@
},
"dependencies": {
"bn.js": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.1.tgz",
- "integrity": "sha512-IUTD/REb78Z2eodka1QZyyEk66pciRcP6Sroka0aI3tG/iwIdYLrBD62RsubR7vqdt3WyX8p4jxeatzmRSphtA=="
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.2.tgz",
+ "integrity": "sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA=="
},
"buffer": {
"version": "5.6.0",
@@ -1687,9 +1687,9 @@
"integrity": "sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA=="
},
"@types/lodash": {
- "version": "4.14.151",
- "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.151.tgz",
- "integrity": "sha512-Zst90IcBX5wnwSu7CAS0vvJkTjTELY4ssKbHiTnGcJgi170uiS8yQDdc3v6S77bRqYQIN1App5a1Pc2lceE5/g=="
+ "version": "4.14.152",
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.152.tgz",
+ "integrity": "sha512-Vwf9YF2x1GE3WNeUMjT5bTHa2DqgUo87ocdgTScupY2JclZ5Nn7W2RLM/N0+oreexUk8uaVugR81NnTY/jNNXg=="
},
"@types/minimatch": {
"version": "3.0.3",
@@ -1717,9 +1717,9 @@
"integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw=="
},
"@types/qs": {
- "version": "6.9.2",
- "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.2.tgz",
- "integrity": "sha512-a9bDi4Z3zCZf4Lv1X/vwnvbbDYSNz59h3i3KdyuYYN+YrLjSeJD0dnphdULDfySvUv6Exy/O0K6wX/kQpnPQ+A=="
+ "version": "6.9.3",
+ "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.3.tgz",
+ "integrity": "sha512-7s9EQWupR1fTc2pSMtXRQ9w9gLOcrJn+h7HOXw4evxyvVqMi4f+q7d2tnFe3ng3SNHjtK+0EzGMGFUQX4/AQRA=="
},
"@types/range-parser": {
"version": "1.2.3",
diff --git a/explorer/package.json b/explorer/package.json
index c2cf21215a..063e314216 100644
--- a/explorer/package.json
+++ b/explorer/package.json
@@ -3,7 +3,7 @@
"version": "0.1.0",
"private": true,
"dependencies": {
- "@solana/web3.js": "^0.49.4",
+ "@solana/web3.js": "^0.51.0",
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2",
diff --git a/explorer/src/components/TransactionDetails.tsx b/explorer/src/components/TransactionDetails.tsx
index caa99e9de4..ed543ccc4e 100644
--- a/explorer/src/components/TransactionDetails.tsx
+++ b/explorer/src/components/TransactionDetails.tsx
@@ -24,6 +24,7 @@ import { StakeDetailsCard } from "./instruction/stake/StakeDetailsCard";
import ErrorCard from "./common/ErrorCard";
import LoadingCard from "./common/LoadingCard";
import TableCardBody from "./common/TableCardBody";
+import { displayTimestamp } from "utils/date";
type Props = { signature: TransactionSignature };
export default function TransactionDetails({ signature }: Props) {
@@ -145,6 +146,13 @@ function StatusCard({ signature }: Props) {
{renderResult()} |
+ {info.timestamp && (
+
+ Timestamp |
+ {displayTimestamp(info.timestamp)} |
+
+ )}
+
Confirmations |
{info.confirmations} |
diff --git a/explorer/src/components/account/StakeAccountCards.tsx b/explorer/src/components/account/StakeAccountCards.tsx
index e4c7e14d3b..f7877abe42 100644
--- a/explorer/src/components/account/StakeAccountCards.tsx
+++ b/explorer/src/components/account/StakeAccountCards.tsx
@@ -4,6 +4,7 @@ import TableCardBody from "components/common/TableCardBody";
import { lamportsToSolString } from "utils";
import Copyable from "components/Copyable";
import { displayAddress } from "utils/tx";
+import { displayTimestamp } from "utils/date";
import { Account, useFetchAccountInfo } from "providers/accounts";
export function StakeAccountCards({
@@ -26,23 +27,10 @@ export function StakeAccountCards({
function LockupCard({ stakeAccount }: { stakeAccount: StakeAccount }) {
const unixTimestamp = stakeAccount.meta?.lockup.unixTimestamp;
if (unixTimestamp && unixTimestamp > 0) {
- const expireDate = new Date(unixTimestamp * 1000);
- const dateString = new Intl.DateTimeFormat("en-US", {
- year: "numeric",
- month: "long",
- day: "numeric"
- }).format(expireDate);
- const timeString = new Intl.DateTimeFormat("en-US", {
- hour: "numeric",
- minute: "numeric",
- second: "numeric",
- hour12: false,
- timeZoneName: "long"
- }).format(expireDate);
- const expireString = `${dateString} at ${timeString}`;
+ const prettyTimestamp = displayTimestamp(unixTimestamp);
return (
- Account is locked! Lockup expires on {expireString}
+ Account is locked! Lockup expires on {prettyTimestamp}
);
} else {
diff --git a/explorer/src/providers/transactions/index.tsx b/explorer/src/providers/transactions/index.tsx
index 770ce01ca9..f70efa2758 100644
--- a/explorer/src/providers/transactions/index.tsx
+++ b/explorer/src/providers/transactions/index.tsx
@@ -5,7 +5,8 @@ import {
SystemProgram,
Account,
SignatureResult,
- PublicKey
+ PublicKey,
+ sendAndConfirmTransaction
} from "@solana/web3.js";
import { useQuery } from "../../utils/url";
import { useCluster, Cluster, ClusterStatus } from "../cluster";
@@ -28,6 +29,7 @@ export type Confirmations = number | "max";
export interface TransactionStatusInfo {
slot: number;
result: SignatureResult;
+ timestamp: number | null;
confirmations: Confirmations;
}
@@ -199,7 +201,12 @@ async function createTestTransaction(
toPubkey: testAccount.publicKey,
lamports: 1
});
- const signature = await connection.sendTransaction(tx, testAccount);
+ const signature = await sendAndConfirmTransaction(
+ connection,
+ tx,
+ [testAccount],
+ 1
+ );
fetchTransactionStatus(dispatch, signature, url, clusterStatus);
} catch (error) {
console.error("Failed to create test failure transaction", error);
@@ -223,11 +230,13 @@ export async function fetchTransactionStatus(
let fetchStatus;
let info: TransactionStatusInfo | undefined;
try {
- const { value } = await new Connection(url).getSignatureStatus(signature, {
+ const connection = new Connection(url);
+ const { value } = await connection.getSignatureStatus(signature, {
searchTransactionHistory: true
});
if (value !== null) {
+ let timestamp = await connection.getBlockTime(value.slot);
let confirmations: Confirmations;
if (typeof value.confirmations === "number") {
confirmations = value.confirmations;
@@ -237,6 +246,7 @@ export async function fetchTransactionStatus(
info = {
slot: value.slot,
+ timestamp,
confirmations,
result: { err: value.err }
};
diff --git a/explorer/src/utils/date.ts b/explorer/src/utils/date.ts
new file mode 100644
index 0000000000..3e9a59f123
--- /dev/null
+++ b/explorer/src/utils/date.ts
@@ -0,0 +1,16 @@
+export function displayTimestamp(unixTimestamp: number): string {
+ const expireDate = new Date(unixTimestamp * 1000);
+ const dateString = new Intl.DateTimeFormat("en-US", {
+ year: "numeric",
+ month: "long",
+ day: "numeric"
+ }).format(expireDate);
+ const timeString = new Intl.DateTimeFormat("en-US", {
+ hour: "numeric",
+ minute: "numeric",
+ second: "numeric",
+ hour12: false,
+ timeZoneName: "long"
+ }).format(expireDate);
+ return `${dateString} at ${timeString}`;
+}