Renamed getStorageAt to getStorage and homestead to mainnet and fixed several Provider formatting bugs.

This commit is contained in:
Richard Moore 2022-09-29 21:55:13 -04:00
parent e14cca31ba
commit 0ce18366b1
10 changed files with 52 additions and 39 deletions

@ -251,7 +251,7 @@ export type PerformActionRequest = {
method: "getLogs", method: "getLogs",
filter: PerformActionFilter filter: PerformActionFilter
} | { } | {
method: "getStorageAt", method: "getStorage",
address: string, position: bigint, blockTag: BlockTag address: string, position: bigint, blockTag: BlockTag
} | { } | {
method: "getTransaction", method: "getTransaction",
@ -273,7 +273,7 @@ export type PerformActionRequest = {
type _PerformAccountRequest = { type _PerformAccountRequest = {
method: "getBalance" | "getTransactionCount" | "getCode" method: "getBalance" | "getTransactionCount" | "getCode"
} | { } | {
method: "getStorageAt", position: bigint method: "getStorage", position: bigint
} }
type CcipArgs = { type CcipArgs = {
@ -795,9 +795,9 @@ export class AbstractProvider implements Provider {
return hexlify(await this.#getAccountValue({ method: "getCode" }, address, blockTag)); return hexlify(await this.#getAccountValue({ method: "getCode" }, address, blockTag));
} }
async getStorageAt(address: AddressLike, _position: BigNumberish, blockTag?: BlockTag): Promise<string> { async getStorage(address: AddressLike, _position: BigNumberish, blockTag?: BlockTag): Promise<string> {
const position = getBigInt(_position, "position"); const position = getBigInt(_position, "position");
return hexlify(await this.#getAccountValue({ method: "getStorageAt", position }, address, blockTag)); return hexlify(await this.#getAccountValue({ method: "getStorage", position }, address, blockTag));
} }
// Write // Write

@ -54,7 +54,7 @@ export function injectCommonNetworks(): void {
} }
} }
registerEth("homestead", 1, { ensNetwork: 1, altNames: [ "mainnet" ] }); registerEth("mainnet", 1, { ensNetwork: 1, altNames: [ "homestead" ] });
registerEth("ropsten", 3, { ensNetwork: 3 }); registerEth("ropsten", 3, { ensNetwork: 3 });
registerEth("rinkeby", 4, { ensNetwork: 4 }); registerEth("rinkeby", 4, { ensNetwork: 4 });
registerEth("goerli", 5, { ensNetwork: 5 }); registerEth("goerli", 5, { ensNetwork: 5 });

@ -1,5 +1,6 @@
import { getAddress, getCreateAddress } from "../address/index.js"; import { getAddress, getCreateAddress } from "../address/index.js";
import { Signature } from "../crypto/index.js"
import { accessListify } from "../transaction/index.js"; import { accessListify } from "../transaction/index.js";
import { import {
getBigInt, getNumber, hexlify, isHexString, zeroPadValue, getBigInt, getNumber, hexlify, isHexString, zeroPadValue,
@ -133,21 +134,23 @@ export const formatReceiptLog = object({
address: getAddress, address: getAddress,
topics: arrayOf(formatHash), topics: arrayOf(formatHash),
data: formatData, data: formatData,
logIndex: getNumber, index: getNumber,
blockHash: formatHash, blockHash: formatHash,
}, {
index: [ "logIndex" ]
}); });
export const formatTransactionReceipt = object({ export const formatTransactionReceipt = object({
to: allowNull(getAddress, null), to: allowNull(getAddress, null),
from: allowNull(getAddress, null), from: allowNull(getAddress, null),
contractAddress: allowNull(getAddress, null), contractAddress: allowNull(getAddress, null),
transactionIndex: getNumber,
// should be allowNull(hash), but broken-EIP-658 support is handled in receipt // should be allowNull(hash), but broken-EIP-658 support is handled in receipt
index: getNumber,
root: allowNull(hexlify), root: allowNull(hexlify),
gasUsed: getBigInt, gasUsed: getBigInt,
logsBloom: allowNull(formatData), logsBloom: allowNull(formatData),
blockHash: formatHash, blockHash: formatHash,
transactionHash: formatHash, hash: formatHash,
logs: arrayOf(formatReceiptLog), logs: arrayOf(formatReceiptLog),
blockNumber: getNumber, blockNumber: getNumber,
confirmations: allowNull(getNumber, null), confirmations: allowNull(getNumber, null),
@ -156,7 +159,9 @@ export const formatTransactionReceipt = object({
status: allowNull(getNumber), status: allowNull(getNumber),
type: getNumber type: getNumber
}, { }, {
effectiveGasPrice: [ "gasPrice" ] effectiveGasPrice: [ "gasPrice" ],
hash: [ "transactionHash" ],
index: [ "transactionIndex" ],
}); });
export function formatTransactionResponse(value: any) { export function formatTransactionResponse(value: any) {
@ -195,10 +200,6 @@ export function formatTransactionResponse(value: any) {
nonce: getNumber, nonce: getNumber,
data: formatData, data: formatData,
r: allowNull(formatUint256),
s: allowNull(formatUint256),
v: allowNull(getNumber),
creates: allowNull(getAddress, null), creates: allowNull(getAddress, null),
chainId: allowNull(getBigInt, null) chainId: allowNull(getBigInt, null)
@ -216,9 +217,19 @@ export function formatTransactionResponse(value: any) {
// Add an access list to supported transaction types // Add an access list to supported transaction types
if ((value.type === 1 || value.type === 2) && value.accessList == null) { if ((value.type === 1 || value.type === 2) && value.accessList == null) {
value.accessList = [ ]; result.accessList = [ ];
} }
// Compute the signature
result.signature = Signature.from(value);
// Some backends omit ChainId on legacy transactions, but we can compute it
if (result.chainId == null) {
const chainId = result.signature.legacyChainId;
if (chainId != null) { result.chainId = chainId; }
}
// @TODO: check chainID // @TODO: check chainID
/* /*
if (value.chainId != null) { if (value.chainId != null) {

@ -177,7 +177,7 @@ export class Network {
*/ */
static from(network?: Networkish): Network { static from(network?: Networkish): Network {
// Default network // Default network
if (network == null) { return Network.from("homestead"); } if (network == null) { return Network.from("mainnet"); }
// Canonical name or chain ID // Canonical name or chain ID
if (typeof(network) === "number") { network = BigInt(network); } if (typeof(network) === "number") { network = BigInt(network); }

@ -16,7 +16,7 @@ const defaultApiKey = "_gg7wSSi0KMBsdKnGVfHDueq6xMB9EkC"
function getHost(name: string): string { function getHost(name: string): string {
switch(name) { switch(name) {
case "homestead": case "mainnet":
return "eth-mainnet.alchemyapi.io"; return "eth-mainnet.alchemyapi.io";
case "ropsten": case "ropsten":
return "eth-ropsten.alchemyapi.io"; return "eth-ropsten.alchemyapi.io";
@ -46,7 +46,7 @@ function getHost(name: string): string {
export class AlchemyProvider extends JsonRpcProvider implements CommunityResourcable { export class AlchemyProvider extends JsonRpcProvider implements CommunityResourcable {
readonly apiKey!: string; readonly apiKey!: string;
constructor(_network: Networkish = "homestead", apiKey?: null | string) { constructor(_network: Networkish = "mainnet", apiKey?: null | string) {
const network = Network.from(_network); const network = Network.from(_network);
if (apiKey == null) { apiKey = defaultApiKey; } if (apiKey == null) { apiKey = defaultApiKey; }

@ -15,7 +15,7 @@ const defaultApiKey = "9f7d929b018cdffb338517efa06f58359e86ff1ffd350bc8897385236
function getHost(name: string): string { function getHost(name: string): string {
switch (name) { switch (name) {
case "homestead": case "mainnet":
return "rpc.ankr.com/eth"; return "rpc.ankr.com/eth";
case "ropsten": case "ropsten":
return "rpc.ankr.com/eth_ropsten"; return "rpc.ankr.com/eth_ropsten";
@ -35,7 +35,7 @@ function getHost(name: string): string {
export class AnkrProvider extends JsonRpcProvider implements CommunityResourcable { export class AnkrProvider extends JsonRpcProvider implements CommunityResourcable {
readonly apiKey!: string; readonly apiKey!: string;
constructor(_network: Networkish = "homestead", apiKey?: null | string) { constructor(_network: Networkish = "mainnet", apiKey?: null | string) {
const network = Network.from(_network); const network = Network.from(_network);
if (apiKey == null) { apiKey = defaultApiKey; } if (apiKey == null) { apiKey = defaultApiKey; }

@ -7,9 +7,9 @@ import type { Networkish } from "./network.js";
export class CloudflareProvider extends JsonRpcProvider { export class CloudflareProvider extends JsonRpcProvider {
constructor(_network: Networkish = "homestead") { constructor(_network: Networkish = "mainnet") {
const network = Network.from(_network); const network = Network.from(_network);
if (network.name !== "homestead") { if (network.name !== "mainnet") {
return throwArgumentError("unsupported network", "network", _network); return throwArgumentError("unsupported network", "network", _network);
} }
super("https:/\/cloudflare-eth.com/", network, { staticNetwork: network }); super("https:/\/cloudflare-eth.com/", network, { staticNetwork: network });

@ -80,7 +80,7 @@ export class BaseEtherscanProvider extends AbstractProvider {
if (this.#plugin) { return this.#plugin.baseUrl; } if (this.#plugin) { return this.#plugin.baseUrl; }
switch(this.network.name) { switch(this.network.name) {
case "homestead": case "mainnet":
return "https:/\/api.etherscan.io"; return "https:/\/api.etherscan.io";
case "ropsten": case "ropsten":
return "https:/\/api-ropsten.etherscan.io"; return "https:/\/api-ropsten.etherscan.io";
@ -353,7 +353,7 @@ export class BaseEtherscanProvider extends AbstractProvider {
tag: req.blockTag tag: req.blockTag
}); });
case "getStorageAt": case "getStorage":
return this.fetch("proxy", { return this.fetch("proxy", {
action: "eth_getStorageAt", action: "eth_getStorageAt",
address: req.address, address: req.address,
@ -486,7 +486,7 @@ export class BaseEtherscanProvider extends AbstractProvider {
} }
async getEtherPrice(): Promise<number> { async getEtherPrice(): Promise<number> {
if (this.network.name !== "homestead") { return 0.0; } if (this.network.name !== "mainnet") { return 0.0; }
return parseFloat((await this.fetch("stats", { action: "ethprice" })).ethusd); return parseFloat((await this.fetch("stats", { action: "ethprice" })).ethusd);
} }

@ -148,7 +148,7 @@ function normalize(provider: AbstractProvider, value: any, req: PerformActionReq
return getNumber(value).toString(); return getNumber(value).toString();
case "getCode": case "getCode":
return hexlify(value); return hexlify(value);
case "getStorageAt": case "getStorage":
return hexlify(value); return hexlify(value);
case "getBlock": case "getBlock":
if (req.includeTransactions) { if (req.includeTransactions) {
@ -450,7 +450,7 @@ export class FallbackProvider extends AbstractProvider {
case "getBalance": case "getBalance":
case "getTransactionCount": case "getTransactionCount":
case "getCode": case "getCode":
case "getStorageAt": case "getStorage":
case "getTransaction": case "getTransaction":
case "getTransactionReceipt": case "getTransactionReceipt":
case "getLogs": case "getLogs":

@ -232,7 +232,7 @@ export class Block<T extends string | TransactionResponse> implements BlockParam
this.#transactions = Object.freeze(block.transactions.map((tx) => { this.#transactions = Object.freeze(block.transactions.map((tx) => {
if (typeof(tx) !== "string" && tx.provider !== provider) { if (typeof(tx) !== "string" && tx.provider !== provider) {
throw new Error("provider mismatch"); return <T>(new TransactionResponse(tx, provider));
} }
return <T>tx; return <T>tx;
}));; }));;
@ -433,14 +433,15 @@ export interface TransactionReceiptParams {
blockNumber: number; blockNumber: number;
logsBloom: string; logsBloom: string;
logs: ReadonlyArray<Log>; logs: ReadonlyArray<LogParams>;
gasUsed: bigint; gasUsed: bigint;
cumulativeGasUsed: bigint; cumulativeGasUsed: bigint;
gasPrice?: null | bigint; gasPrice?: null | bigint;
effectiveGasPrice?: null | bigint; effectiveGasPrice?: null | bigint;
byzantium: boolean; type: number;
//byzantium: boolean;
status: null | number; status: null | number;
root: null | string; root: null | string;
} }
@ -478,7 +479,8 @@ export class TransactionReceipt implements TransactionReceiptParams, Iterable<Lo
readonly cumulativeGasUsed!: bigint; readonly cumulativeGasUsed!: bigint;
readonly gasPrice!: bigint; readonly gasPrice!: bigint;
readonly byzantium!: boolean; readonly type!: number;
//readonly byzantium!: boolean;
readonly status!: null | number; readonly status!: null | number;
readonly root!: null | string; readonly root!: null | string;
@ -486,11 +488,7 @@ export class TransactionReceipt implements TransactionReceiptParams, Iterable<Lo
constructor(tx: TransactionReceiptParams, provider: Provider) { constructor(tx: TransactionReceiptParams, provider: Provider) {
this.#logs = Object.freeze(tx.logs.map((log) => { this.#logs = Object.freeze(tx.logs.map((log) => {
if (provider !== log.provider) { return new Log(log, provider);
//return log.connect(provider);
throw new Error("provider mismatch");
}
return log;
})); }));
defineProperties<TransactionReceipt>(this, { defineProperties<TransactionReceipt>(this, {
@ -512,7 +510,8 @@ export class TransactionReceipt implements TransactionReceiptParams, Iterable<Lo
cumulativeGasUsed: tx.cumulativeGasUsed, cumulativeGasUsed: tx.cumulativeGasUsed,
gasPrice: ((tx.effectiveGasPrice || tx.gasPrice) as bigint), gasPrice: ((tx.effectiveGasPrice || tx.gasPrice) as bigint),
byzantium: tx.byzantium, type: tx.type,
//byzantium: tx.byzantium,
status: tx.status, status: tx.status,
root: tx.root root: tx.root
}); });
@ -527,12 +526,15 @@ export class TransactionReceipt implements TransactionReceiptParams, Iterable<Lo
toJSON(): any { toJSON(): any {
const { const {
to, from, contractAddress, hash, index, blockHash, blockNumber, logsBloom, to, from, contractAddress, hash, index, blockHash, blockNumber, logsBloom,
logs, byzantium, status, root logs, //byzantium,
status, root
} = this; } = this;
return { return {
_type: "TransactionReceipt", _type: "TransactionReceipt",
blockHash, blockNumber, byzantium, contractAddress, blockHash, blockNumber,
//byzantium,
contractAddress,
cumulativeGasUsed: toJson(this.cumulativeGasUsed), cumulativeGasUsed: toJson(this.cumulativeGasUsed),
from, from,
gasPrice: toJson(this.gasPrice), gasPrice: toJson(this.gasPrice),
@ -1104,7 +1106,7 @@ export interface Provider extends ContractRunner, EventEmitterable<ProviderEvent
* @note On nodes without archive access enabled, the %%blockTag%% may be * @note On nodes without archive access enabled, the %%blockTag%% may be
* **silently ignored** by the node, which may cause issues if relied on. * **silently ignored** by the node, which may cause issues if relied on.
*/ */
getStorageAt(address: AddressLike, position: BigNumberish, blockTag?: BlockTag): Promise<string> getStorage(address: AddressLike, position: BigNumberish, blockTag?: BlockTag): Promise<string>
//////////////////// ////////////////////