I am building a dApp with ethersjs and metamask and everything works fine however, I want to be able to get the chain explorer so users can check the details of their transaction.
At the moment, new ethers.providers.Web3Provider(window.ethereum).network gives me the chain ID but not the block explorer URL as in https://goerli.etherscan.io/ for goerli test net.
How can I get the block explorer of any chain ID?
Ethers doesn't have information about the block explorers, they're external services. But you can use this library from metamask: https://github.com/MetaMask/etherscan-link it will generate a block explorer url from a given chainId.
The other option is to hardcode a map of chainIds to block explorer URLs, which may sound like a bad idea but at least you're in control of where you're pointing your users towards, instead of passing on that responsibility to another library
I think with ethers v6 which was published a few days ago you can get specific data about Block and its transactions.
import { BrowserProvider ,Block} from "ethers";
const providerr = new BrowserProvider(window.ethereum);
this is Block constructor sign
constructor(block: BlockParams, provider: Provider) {}
this is BlockParams
export interface BlockParams {
hash?: null | string;
number: number;
timestamp: number;
parentHash: string;
nonce: string;
difficulty: bigint;
gasLimit: bigint;
gasUsed: bigint;
miner: string;
extraData: string;
baseFeePerGas: null | bigint;
transactions: ReadonlyArray<string | TransactionResponseParams>;
};
once you created a Block instance, you can access all the methods. Check the source code of Block class in node_modules
Related
Im sure this is a really common issue but I just cannot seem to find any accepted solutions.
When combining typeorm and typegraphql, you create entities with the properties of the entity. However typeorm also allows for hooks such as beforeInsert to be added to the entity.
The issue im having is that the entity includes these hooks as properties which are not returned from the database e.g.
// Define the entity
#Entity()
#ObjectType()
export class MyEntity extends CustomBaseEntity {
#Field(() => ID)
#PrimaryGeneratedColumn("uuid")
id: string;
#Field()
#Column({ type: "bigint", nullable: true })
created: number;
#BeforeInsert()
beforeUpdate() {
this.created = Date.now();
}
}
// Pull the entity from the database
const myEntityRow = myEntityRepository.findOneWhere({id})
// As you can see there is a type mismatch
// The type is MyEntity type (including the beforeInsert method) even though there is no
// beforeInsert prop on the actual entity
console.log(
myEntityRow // { id: 1, created: 123 }
)
Meaning that something like this does not work:
const destructuredEntity = {...myEntityRow}
await myEntityRepository.save(destructuredEntity) // Typeerror - missing properties "beforeInsert"
Right now i'm probably just thinking that I need to remove these hook functions and just put any methods like this within the service, any ideas?
and just put any methods like this within the service, any ideas?
that's definitely the best choice.
It's better not to use inversion of control in case you can avoid it or you don't have some significant advantages because of using it.
Just put created initialization in constructor or make it default in your database.
I am using the interface to define a type of variable and initializing that variable with a class that has some additional properties than the interface.
please refer to the code below:
interface User {
name: string;
id: number;
}
class UserAccount {
name: string;
id: number;
username: string
constructor(name: string, id: number, username: string) {
this.name = name;
this.id = id;
this.username = username;
}
}
const user: User = new UserAccount("Suraj", 1, "srs");
// user.username
// I will not be able to access username in above line but when I console it, it will show the value assigned by the class constructor
console.log(user)
// output will be **UserAccount { name: 'Murphy', id: 1, username: 'srs' }**
My question is:
Why we are using Interface when we are initializing variables with the class?
And if we are using this then why it is not an error in the typescript when compiling?
And last if we are able to assign it (UserAccount { name: 'Murphy', id: 1, username: 'srs' }) then why can't we access user.username?
(Typing from phone, can add details later)
For starters you are not using the interface.
You defined a class and an interface that are completely unrelated and only have similar names.
To actually use the interface you’d have to do something like:
class UserAccount implements User {
…
}
Now answering your questions:
There many reasons one would create interfaces.
For instance you could share the interface with a different parte of the code letting it know what a UserAccount looks like without creating a dependency on the class itself.
Another user can be to define multiple interfaces such as “SoundPlayer” and “GraphicsPlayer”, then have a class implement one or both. Those classes could represent a music player by implementing “SoundPlayer” or a multimedia player by implementing both.
This also ensures that classes with similar functions “look the same”.
Not sure what you’re asking but I feel like you were expecting some sort of error that won’t occur since you’re not actually implementing the interface.
You can’t access user.username because it is part of the class UserAccount and not part of the interface.
I have some nested interfaces in typescript, sort of like this:
export interface Person {
name: string;
age: number;
status: Status;
}
export interface Status {
location: string;
activity: number;
}
When I get a Person from my server and I want to console.log it, I can do this:
console.log(JSON.stringify(person))
This works fine for the top level Person fields, but it just prints "Object" for the status field. I know this is because Status is an interface and does not have a toJSON method. So, I need to get some method to "jsonify" an entire structure of nested interfaces, ie where none of the interfaces have a toJSON method.
How do I do this?
UPDATE: So it turns out everything was indeed working perfectly. The issue is that console.log will only go down to a certain depth (like 2) before it starts printing things like '[Object]' or '[Array]'. To see the full printout I used this instead:
console.dir(myobject, {depth: null});
Apparently this works just like console.log but does the full printout to arbitrary depth.
I have an User interface like this
interface IUser {
name: string,
phoneNumber: string
}
and a PublicUser interface like this
interface IPublicUser {
name: string
}
What i'm trying to do it's from an object of type IUser return only public informations.
I tried something like this :
const user: IUser = {
name: 'Eliott',
phoneNumber : '+1...'
}
console.log(user as unknown as IPublicUser)
But always return the full user.
My temporary fix it's to create a method toPublicJson to return only the desired field, but it's not very good, because if my interface change I must also change this method..
Do you have some advices ?
Thanks
You must remember that TypeScript compiles to JavaScript. Statements like variable as type get lost in transpilation. They are just hints to the transpiler and the user, but they don't really mean anything. In the same way, interfaces are just hints and help for the compiler, by they really meant nothing at runtime.
If you want to do that, you still have to do it by hand, to create another object with the properties you want:
const publicUser : IPublicUser = { name: user.name };
Of course, you may only care about what other programmers see when dealing with your code, so, in that way, they'll just see IPublicUser and if they want to use a property that its not in that interface, they'll get a compiler error. But if you care about what is really happening when the code is executing, then you have to do it explicitly.
I design Event Model of my server, which contains a lot of events related to many users. For example (since I use javascript SDK, let me describe the structure with Typescript):
interface IEventBase {
user: Parse.User;
}
interface IEventStartWork extends IEventBase {
late: boolean;
}
interface IEventAfterWork extends IEventBase {
jobDone: boolean;
}
interface IEventDrinkWaters extends IEventBase {
howManyTimes: number;
}
interface IEventGoOutForLunch extends IEventBase {
howLong: number;
}
In my case, I have more than 100 different kind of events, and I need to take all events happened to one user as fast as possible. And I cannot put them into one single collection, because I have to add index on each event when necessary. So I attempt to put them into one indexed, collection with pointer:
interface IEvents {
user: Parse.User;
pointer: IEventBase;
}
By this design I can quickly pull out all events of an user, in any time range.
But then I got error when storing different events into Events collection, showing error:
schema mismatch for Events.entity; expected Pointer<EventStartWork> but got Pointer<EventAfterWork>
What can I do to achieve this goal with Parse Server, maybe disable schema checking on single field?