@mentaproject/client 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/structures/Account.d.ts +12 -5
- package/dist/structures/Account.js +39 -5
- package/dist/structures/Block.d.ts +1 -0
- package/dist/structures/Block.js +7 -0
- package/dist/structures/ContractAccount.d.ts +6 -0
- package/dist/structures/ContractAccount.js +12 -0
- package/dist/structures/Transaction.d.ts +9 -0
- package/dist/structures/Transaction.js +29 -1
- package/dist/structures/minimal.d.ts +20 -0
- package/dist/structures/minimal.js +62 -0
- package/dist/utils/toJSON.d.ts +9 -0
- package/dist/utils/toJSON.js +71 -0
- package/package.json +5 -4
- package/test.ts +6 -45
|
@@ -2,10 +2,10 @@ import type { Address, CoreClient } from "@mentaproject/core/types";
|
|
|
2
2
|
import { Transaction } from "./Transaction";
|
|
3
3
|
import { GetTransactionsReturnType } from "../types/Account";
|
|
4
4
|
/**
|
|
5
|
-
* Represents
|
|
5
|
+
* Represents an account with methods for interacting with it.
|
|
6
6
|
*/
|
|
7
7
|
export declare class Account {
|
|
8
|
-
|
|
8
|
+
rpcClient: CoreClient;
|
|
9
9
|
address: Address;
|
|
10
10
|
/**
|
|
11
11
|
* Creates an instance of Account.
|
|
@@ -13,6 +13,12 @@ export declare class Account {
|
|
|
13
13
|
* @param address The blockchain address of the account.
|
|
14
14
|
*/
|
|
15
15
|
constructor(rpcClient: CoreClient, address: Address);
|
|
16
|
+
/**
|
|
17
|
+
* If the account is a contract, returns a ContractAccount instance. Otherwise, returns undefined.
|
|
18
|
+
* @returns
|
|
19
|
+
*/
|
|
20
|
+
isContract(): Promise<boolean>;
|
|
21
|
+
contractType(): Promise<any>;
|
|
16
22
|
/**
|
|
17
23
|
* Sends native cryptocurrency (ETH) to the account.
|
|
18
24
|
* @param amount The amount of ETH to send (in wei).
|
|
@@ -23,12 +29,12 @@ export declare class Account {
|
|
|
23
29
|
* Gets the native cryptocurrency (ETH) balance of the account.
|
|
24
30
|
* @returns A Promise that resolves to the ETH balance (in wei).
|
|
25
31
|
*/
|
|
26
|
-
|
|
32
|
+
ETHBalance(): Promise<bigint>;
|
|
27
33
|
/**
|
|
28
34
|
* Gets the transaction count (nonce) for the account.
|
|
29
35
|
* @returns A Promise that resolves to the transaction count.
|
|
30
36
|
**/
|
|
31
|
-
|
|
37
|
+
transactionCount(): Promise<number>;
|
|
32
38
|
/**
|
|
33
39
|
* Get all transactions involving this account in the given block range.
|
|
34
40
|
* NOTE: This method relies on the non-standard 'trace_filter' method of the RPC. It may not be supported by all nodes.
|
|
@@ -37,5 +43,6 @@ export declare class Account {
|
|
|
37
43
|
*
|
|
38
44
|
* @returns A paginated result containing the transaction hashes.
|
|
39
45
|
*/
|
|
40
|
-
|
|
46
|
+
transactions(toRetreive?: number): Promise<GetTransactionsReturnType>;
|
|
47
|
+
toJSON(depth?: number): Promise<any>;
|
|
41
48
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { createBlockRangePager, getBalance, getBlockNumber, getTransaction, getTransactionCount, sendTransaction, traceFilter } from "@mentaproject/core/actions";
|
|
1
|
+
import { createBlockRangePager, getBalance, getBlockNumber, getCode, getTransaction, getTransactionCount, sendTransaction, traceFilter } from "@mentaproject/core/actions";
|
|
2
2
|
import { Transaction } from "./Transaction";
|
|
3
3
|
import { toHex } from "@mentaproject/core/utils";
|
|
4
|
+
import { getContractType } from "@mentaproject/contracts";
|
|
5
|
+
import { toJSON } from "src/utils/toJSON";
|
|
4
6
|
/**
|
|
5
|
-
* Represents
|
|
7
|
+
* Represents an account with methods for interacting with it.
|
|
6
8
|
*/
|
|
7
9
|
export class Account {
|
|
8
10
|
/**
|
|
@@ -14,6 +16,24 @@ export class Account {
|
|
|
14
16
|
this.rpcClient = rpcClient;
|
|
15
17
|
this.address = address;
|
|
16
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* If the account is a contract, returns a ContractAccount instance. Otherwise, returns undefined.
|
|
21
|
+
* @returns
|
|
22
|
+
*/
|
|
23
|
+
async isContract() {
|
|
24
|
+
const code = await getCode(this.rpcClient, { address: this.address });
|
|
25
|
+
if (!code || code === "0x")
|
|
26
|
+
return false;
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
;
|
|
30
|
+
async contractType() {
|
|
31
|
+
const isContract = await this.isContract();
|
|
32
|
+
if (!isContract)
|
|
33
|
+
return undefined;
|
|
34
|
+
return await getContractType(this.rpcClient, this.address);
|
|
35
|
+
}
|
|
36
|
+
;
|
|
17
37
|
/**
|
|
18
38
|
* Sends native cryptocurrency (ETH) to the account.
|
|
19
39
|
* @param amount The amount of ETH to send (in wei).
|
|
@@ -34,7 +54,7 @@ export class Account {
|
|
|
34
54
|
* Gets the native cryptocurrency (ETH) balance of the account.
|
|
35
55
|
* @returns A Promise that resolves to the ETH balance (in wei).
|
|
36
56
|
*/
|
|
37
|
-
async
|
|
57
|
+
async ETHBalance() {
|
|
38
58
|
// Assurez-vous que rpcClient est bien un PublicClient ou WalletClient
|
|
39
59
|
return await getBalance(this.rpcClient, {
|
|
40
60
|
address: this.address,
|
|
@@ -45,7 +65,7 @@ export class Account {
|
|
|
45
65
|
* Gets the transaction count (nonce) for the account.
|
|
46
66
|
* @returns A Promise that resolves to the transaction count.
|
|
47
67
|
**/
|
|
48
|
-
async
|
|
68
|
+
async transactionCount() {
|
|
49
69
|
return await getTransactionCount(this.rpcClient, { address: this.address });
|
|
50
70
|
}
|
|
51
71
|
/**
|
|
@@ -56,7 +76,7 @@ export class Account {
|
|
|
56
76
|
*
|
|
57
77
|
* @returns A paginated result containing the transaction hashes.
|
|
58
78
|
*/
|
|
59
|
-
async
|
|
79
|
+
async transactions(toRetreive = 10) {
|
|
60
80
|
const currentBlock = await getBlockNumber(this.rpcClient);
|
|
61
81
|
const onBlockRange = async ({ fromBlock, toBlock }) => {
|
|
62
82
|
const outgoing = await traceFilter(this.rpcClient, {
|
|
@@ -83,4 +103,18 @@ export class Account {
|
|
|
83
103
|
itemsPerPage: toRetreive
|
|
84
104
|
}, onBlockRange);
|
|
85
105
|
}
|
|
106
|
+
;
|
|
107
|
+
async toJSON(depth = 1) {
|
|
108
|
+
return await toJSON({
|
|
109
|
+
obj: {
|
|
110
|
+
...this,
|
|
111
|
+
isContract: this.isContract,
|
|
112
|
+
contractType: this.contractType,
|
|
113
|
+
ETHBalance: this.ETHBalance,
|
|
114
|
+
transactionCount: this.transactionCount,
|
|
115
|
+
},
|
|
116
|
+
depth
|
|
117
|
+
});
|
|
118
|
+
}
|
|
86
119
|
}
|
|
120
|
+
;
|
package/dist/structures/Block.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Account } from "./Account";
|
|
2
2
|
import { Transaction } from "./Transaction";
|
|
3
|
+
import { toJSON } from "src/utils/toJSON";
|
|
3
4
|
export class Block {
|
|
4
5
|
constructor(rpcClient, data, includeTransactions = false) {
|
|
5
6
|
this.rpcClient = rpcClient;
|
|
@@ -33,5 +34,11 @@ export class Block {
|
|
|
33
34
|
this.transactions = data.transactions.map((txData) => new Transaction(this.rpcClient, txData));
|
|
34
35
|
}
|
|
35
36
|
;
|
|
37
|
+
async toJSON(depth = 1) {
|
|
38
|
+
return await toJSON({
|
|
39
|
+
obj: this,
|
|
40
|
+
depth
|
|
41
|
+
});
|
|
42
|
+
}
|
|
36
43
|
}
|
|
37
44
|
;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Account } from "./Account";
|
|
2
|
+
import { getContractType } from "@mentaproject/contracts";
|
|
3
|
+
export class ContractAccount extends Account {
|
|
4
|
+
constructor(rpcClient, address) {
|
|
5
|
+
super(rpcClient, address);
|
|
6
|
+
}
|
|
7
|
+
;
|
|
8
|
+
async getType() {
|
|
9
|
+
return await getContractType(this.rpcClient, this.address);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
;
|
|
@@ -24,7 +24,16 @@ export declare class Transaction implements Omit<ITransactionData, "from" | "to"
|
|
|
24
24
|
from?: Account;
|
|
25
25
|
to?: Account;
|
|
26
26
|
constructor(rpcClient: CoreClient, data: ITransactionData);
|
|
27
|
+
calls(): Promise<{
|
|
28
|
+
from: Account;
|
|
29
|
+
to: Account;
|
|
30
|
+
value: bigint;
|
|
31
|
+
input: Hex;
|
|
32
|
+
gas: bigint;
|
|
33
|
+
callType: string | undefined;
|
|
34
|
+
}[]>;
|
|
27
35
|
waitForReceipt(confirmations?: number): Promise<WaitForTransactionReceiptReturnType>;
|
|
28
36
|
receipt(): Promise<WaitForTransactionReceiptReturnType>;
|
|
29
37
|
block(): Promise<Block>;
|
|
38
|
+
toJSON(depth?: number): Promise<any>;
|
|
30
39
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Account } from './Account';
|
|
2
2
|
import { Block } from './Block';
|
|
3
|
-
import { getBlock, getTransactionReceipt, waitForTransactionReceipt } from '@mentaproject/core/actions';
|
|
3
|
+
import { getBlock, getTransactionReceipt, traceTransaction, waitForTransactionReceipt } from '@mentaproject/core/actions';
|
|
4
|
+
import { hexToBigInt } from '@mentaproject/core/utils';
|
|
5
|
+
import { toJSON } from 'src/utils/toJSON';
|
|
4
6
|
export class Transaction {
|
|
5
7
|
constructor(rpcClient, data) {
|
|
6
8
|
this.rpcClient = rpcClient;
|
|
@@ -25,6 +27,18 @@ export class Transaction {
|
|
|
25
27
|
this.to = data.to ? new Account(this.rpcClient, data.to) : undefined;
|
|
26
28
|
}
|
|
27
29
|
;
|
|
30
|
+
async calls() {
|
|
31
|
+
const traces = await traceTransaction(this.rpcClient, this.hash);
|
|
32
|
+
const calls = traces.filter(t => t.type === "call" && t.action !== undefined);
|
|
33
|
+
return calls.map(c => ({
|
|
34
|
+
from: new Account(this.rpcClient, c.action.from),
|
|
35
|
+
to: new Account(this.rpcClient, c.action.to),
|
|
36
|
+
value: hexToBigInt(c.action.value),
|
|
37
|
+
input: c.action.input,
|
|
38
|
+
gas: hexToBigInt(c.action.gas),
|
|
39
|
+
callType: c.action.callType,
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
28
42
|
async waitForReceipt(confirmations) {
|
|
29
43
|
return await waitForTransactionReceipt(this.rpcClient, {
|
|
30
44
|
hash: this.hash,
|
|
@@ -41,5 +55,19 @@ export class Transaction {
|
|
|
41
55
|
return new Block(this.rpcClient, data);
|
|
42
56
|
}
|
|
43
57
|
;
|
|
58
|
+
async toJSON(depth = 1) {
|
|
59
|
+
return await toJSON({
|
|
60
|
+
obj: {
|
|
61
|
+
...this,
|
|
62
|
+
block: this.block,
|
|
63
|
+
receipt: this.receipt,
|
|
64
|
+
calls: async () => {
|
|
65
|
+
const calls = await this.calls();
|
|
66
|
+
return Promise.all(calls.map(async (c) => await toJSON({ obj: c, depth: depth })));
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
depth
|
|
70
|
+
});
|
|
71
|
+
}
|
|
44
72
|
}
|
|
45
73
|
;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
declare class BaseService {
|
|
2
|
+
id: string;
|
|
3
|
+
rpcClient: any;
|
|
4
|
+
address: string;
|
|
5
|
+
constructor(id: string, rpcClient: any, address: string);
|
|
6
|
+
protected fetchCode(): Promise<string | null>;
|
|
7
|
+
}
|
|
8
|
+
type ContractService = BaseService & {
|
|
9
|
+
isContractMarker: true;
|
|
10
|
+
getContractDetails: () => string;
|
|
11
|
+
};
|
|
12
|
+
declare class AccountVerifier extends BaseService {
|
|
13
|
+
isContractMarker?: true;
|
|
14
|
+
getContractDetails?: () => string;
|
|
15
|
+
/**
|
|
16
|
+
* Vérifie si le compte est un contrat.
|
|
17
|
+
*/
|
|
18
|
+
isContractAccount(): Promise<this is ContractService>;
|
|
19
|
+
processAccount(): Promise<void>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// test-guard.ts
|
|
3
|
+
// Simulez vos dépendances externes si nécessaire pour ce test
|
|
4
|
+
// Par exemple :
|
|
5
|
+
// declare function getCode(rpcClient: any, params: { address: string }): Promise<string | null | undefined>;
|
|
6
|
+
// interface RpcClientType {}
|
|
7
|
+
// Définition de la classe de base
|
|
8
|
+
class BaseService {
|
|
9
|
+
constructor(id, rpcClient, address) {
|
|
10
|
+
this.id = id;
|
|
11
|
+
this.rpcClient = rpcClient;
|
|
12
|
+
this.address = address;
|
|
13
|
+
}
|
|
14
|
+
// Méthode pour simuler l'appel externe
|
|
15
|
+
async fetchCode() {
|
|
16
|
+
// Remplacez par votre vrai appel à getCode si possible pour le test,
|
|
17
|
+
// ou utilisez ce mock :
|
|
18
|
+
console.log(`Workspaceing code for ${this.address} using client ${this.rpcClient}`);
|
|
19
|
+
if (this.address === "contract_address") {
|
|
20
|
+
return "0x12345"; // code de contrat valide
|
|
21
|
+
}
|
|
22
|
+
return "0x"; // pas de code ou compte externe
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
// Classe contenant le type guard asynchrone
|
|
26
|
+
class AccountVerifier extends BaseService {
|
|
27
|
+
/**
|
|
28
|
+
* Vérifie si le compte est un contrat.
|
|
29
|
+
*/
|
|
30
|
+
async isContractAccount() {
|
|
31
|
+
const code = await this.fetchCode(); // Utilise la méthode de la classe (ou de la base)
|
|
32
|
+
if (code && typeof code === 'string' && code !== '0x' && code.length > 2) {
|
|
33
|
+
// Logique pour rendre 'this' conforme à ContractService
|
|
34
|
+
this.isContractMarker = true;
|
|
35
|
+
this.getContractDetails = () => `Details for contract ${this.address}`;
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
delete this.isContractMarker;
|
|
40
|
+
delete this.getContractDetails;
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async processAccount() {
|
|
45
|
+
if (await this.isContractAccount()) {
|
|
46
|
+
// Ici, 'this' est affiné en ContractService
|
|
47
|
+
console.log(`Account ${this.id} (${this.address}) is a contract.`);
|
|
48
|
+
console.log(this.getContractDetails());
|
|
49
|
+
console.log(`Marker: ${this.isContractMarker}`);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
// Ici, 'this' est AccountVerifier (ou BaseService)
|
|
53
|
+
console.log(`Account ${this.id} (${this.address}) is not a contract.`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// Test
|
|
58
|
+
// const mockRpcClient: RpcClientType = {}; // Votre client RPC
|
|
59
|
+
// const verifier1 = new AccountVerifier("service1", mockRpcClient, "contract_address");
|
|
60
|
+
// const verifier2 = new AccountVerifier("service2", mockRpcClient, "eoa_address");
|
|
61
|
+
// verifier1.processAccount();
|
|
62
|
+
// verifier2.processAccount();
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
function isClassInstance(obj) {
|
|
2
|
+
if (obj === null || typeof obj !== 'object' || !obj.constructor) {
|
|
3
|
+
return false;
|
|
4
|
+
}
|
|
5
|
+
// Les constructeurs de classes ES6 commencent par "class " quand on les convertit en string.
|
|
6
|
+
// Attention: cela peut être sensible à la minification ou à des transpilers très spécifiques,
|
|
7
|
+
// mais c'est généralement fiable pour les classes définies avec le mot-clé `class`.
|
|
8
|
+
return obj.constructor.toString().startsWith('class ');
|
|
9
|
+
}
|
|
10
|
+
;
|
|
11
|
+
function convertBigintsToStrings(obj) {
|
|
12
|
+
if (typeof obj === 'bigint') {
|
|
13
|
+
return obj.toString();
|
|
14
|
+
}
|
|
15
|
+
if (typeof obj === 'object') {
|
|
16
|
+
for (const key in obj) {
|
|
17
|
+
obj[key] = convertBigintsToStrings(obj[key]);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
if (Array.isArray(obj)) {
|
|
21
|
+
for (let i = 0; i < obj.length; i++) {
|
|
22
|
+
obj[i] = convertBigintsToStrings(obj[i]);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return obj;
|
|
26
|
+
}
|
|
27
|
+
export async function toJSON({ obj, depth = 0 }) {
|
|
28
|
+
// copy the properties of the object
|
|
29
|
+
const data = Object.assign({}, obj);
|
|
30
|
+
for (const key in obj) {
|
|
31
|
+
// skip class related properties
|
|
32
|
+
if (key === "toJSON" || key === "constructor" || key === "rpcClient") {
|
|
33
|
+
delete data[key];
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
;
|
|
37
|
+
const prop = obj[key];
|
|
38
|
+
if (typeof prop === "function") {
|
|
39
|
+
// do not fetch getters if depth is 0
|
|
40
|
+
if (depth === 0) {
|
|
41
|
+
delete data[key];
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
// fetch getters
|
|
45
|
+
const value = await obj[key]();
|
|
46
|
+
// if the value is a class instance, convert it to JSON recursively
|
|
47
|
+
if (typeof value === "object" && isClassInstance(value)) {
|
|
48
|
+
data[key] = await toJSON({ obj: value, depth: depth - 1 });
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
data[key] = value;
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (typeof prop === "object" && isClassInstance(prop)) {
|
|
55
|
+
// If depth is 0, just flatten the object using recursion
|
|
56
|
+
if (depth === 0) {
|
|
57
|
+
data[key] = await toJSON({
|
|
58
|
+
obj: prop,
|
|
59
|
+
depth: depth - 1
|
|
60
|
+
});
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
;
|
|
64
|
+
// If depth is not 0, fetch the object
|
|
65
|
+
data[key] = await prop.toJSON({ depth: depth - 1 });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
;
|
|
69
|
+
return convertBigintsToStrings(data);
|
|
70
|
+
}
|
|
71
|
+
;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mentaproject/client",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "High level EVM library used into the Menta App to facilitate Blockchain interactions. ",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -29,14 +29,15 @@
|
|
|
29
29
|
"author": "@mentaproject",
|
|
30
30
|
"license": "ISC",
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@
|
|
33
|
-
"@mentaproject/
|
|
34
|
-
"@
|
|
32
|
+
"@mentaproject/contracts": "^0.0.8",
|
|
33
|
+
"@mentaproject/core": "^0.0.4",
|
|
34
|
+
"@shazow/whatsabi": "^0.21.1"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@rollup/plugin-commonjs": "^28.0.3",
|
|
38
38
|
"@rollup/plugin-node-resolve": "^16.0.1",
|
|
39
39
|
"@rollup/plugin-typescript": "^12.1.2",
|
|
40
|
+
"@types/node": "^22.15.29",
|
|
40
41
|
"rollup": "^4.40.1",
|
|
41
42
|
"tslib": "^2.8.1",
|
|
42
43
|
"tsx": "^4.19.4",
|
package/test.ts
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { http } from "viem";
|
|
2
2
|
import { MentaClient } from "./src";
|
|
3
3
|
import { privateKeyToAccount, generatePrivateKey } from "viem/accounts"
|
|
4
4
|
import { mainnet } from "@mentaproject/core/chains";
|
|
5
|
-
|
|
6
|
-
import {
|
|
7
|
-
import { toFunctionSignature } from "viem"
|
|
8
|
-
import { bytes32ToAddress } from "@mentaproject/core/utils";
|
|
5
|
+
|
|
6
|
+
import { writeFileSync } from "fs";
|
|
9
7
|
|
|
10
8
|
const viemAccount = privateKeyToAccount(generatePrivateKey());
|
|
11
9
|
|
|
@@ -16,45 +14,8 @@ const client = new MentaClient({
|
|
|
16
14
|
});
|
|
17
15
|
|
|
18
16
|
(async () => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
// const log = receipt.logs[0];
|
|
23
|
-
|
|
24
|
-
// if (!log) return;
|
|
25
|
-
|
|
26
|
-
// const decoded = decodeEventLog({
|
|
27
|
-
// abi: erc20Abi,
|
|
28
|
-
// data: receipt.logs[0].data,
|
|
29
|
-
// topics: receipt.logs[0].topics,
|
|
30
|
-
// });
|
|
31
|
-
|
|
32
|
-
// console.log(decoded.args)
|
|
33
|
-
|
|
34
|
-
const erc20Signatures = erc20Abi.filter(item => item.type === "function").map(item => ({ signature:toFunctionSignature(item), selector: toFunctionSelector(item)}));
|
|
35
|
-
|
|
36
|
-
const code = await getCode(client.rpcClient, { address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" });
|
|
37
|
-
const infos = selectorsFromBytecode(code as string);
|
|
38
|
-
|
|
39
|
-
console.log(infos);
|
|
40
|
-
|
|
41
|
-
async function getImplementationAddress(proxyAddr: Address) {
|
|
42
|
-
const storageValue = await getStorageAt(client.rpcClient, {
|
|
43
|
-
address: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
|
|
44
|
-
slot: "0x7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c3"
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
if (storageValue) {
|
|
48
|
-
|
|
49
|
-
console.log(storageValue);
|
|
50
|
-
// La valeur retournée est un hex de 32 octets. L'adresse est dans les 20 derniers octets.
|
|
51
|
-
const address = getAddress(bytes32ToAddress(storageValue))
|
|
52
|
-
if (address !== zeroAddress) {
|
|
53
|
-
return address;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
return null; // Pas d'adresse trouvée ou contrat non EIP-1967
|
|
57
|
-
};
|
|
17
|
+
const firstTx = await client.transactions.get({ hash: "0xeae261aeada2db19fee5cc4dfd47d575ff2380a5fb6a4039685d5044fdc8e2bb" });
|
|
18
|
+
const json = await firstTx.toJSON(2);
|
|
58
19
|
|
|
59
|
-
|
|
20
|
+
writeFileSync("./test.json", JSON.stringify(json, null, 2));
|
|
60
21
|
})()
|