@rocketh/core 0.17.7 → 0.17.9
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/README.md +6 -0
- package/dist/account.d.ts +43 -0
- package/dist/account.d.ts.map +1 -0
- package/dist/account.js +61 -0
- package/dist/account.js.map +1 -0
- package/dist/account.test.d.ts +2 -0
- package/dist/account.test.d.ts.map +1 -0
- package/dist/account.test.js +324 -0
- package/dist/account.test.js.map +1 -0
- package/dist/artifacts.test.d.ts +2 -0
- package/dist/artifacts.test.d.ts.map +1 -0
- package/dist/artifacts.test.js +682 -0
- package/dist/artifacts.test.js.map +1 -0
- package/dist/environment.integration.test.d.ts +13 -0
- package/dist/environment.integration.test.d.ts.map +1 -0
- package/dist/environment.integration.test.js +296 -0
- package/dist/environment.integration.test.js.map +1 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/json.test.d.ts +2 -0
- package/dist/json.test.d.ts.map +1 -0
- package/dist/json.test.js +383 -0
- package/dist/json.test.js.map +1 -0
- package/dist/providers/TransactionHashTracker.d.ts.map +1 -1
- package/dist/providers/TransactionHashTracker.js +3 -0
- package/dist/providers/TransactionHashTracker.js.map +1 -1
- package/dist/providers/TransactionHashTracker.test.d.ts +2 -0
- package/dist/providers/TransactionHashTracker.test.d.ts.map +1 -0
- package/dist/providers/TransactionHashTracker.test.js +284 -0
- package/dist/providers/TransactionHashTracker.test.js.map +1 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +16 -7
- package/src/account.ts +74 -0
- package/src/artifacts.ts +176 -0
- package/src/environment.ts +98 -0
- package/src/index.ts +24 -0
- package/src/json.ts +63 -0
- package/src/providers/BaseProvider.ts +13 -0
- package/src/providers/TransactionHashTracker.ts +26 -0
- package/src/providers/index.ts +1 -0
- package/src/types.ts +637 -0
package/src/artifacts.ts
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import type {Abi} from 'abitype';
|
|
2
|
+
import type {Artifact, DevDoc, UserDoc} from './types.js';
|
|
3
|
+
import {toFunctionSelector} from 'viem';
|
|
4
|
+
|
|
5
|
+
type CreateMutable<Type> = {
|
|
6
|
+
-readonly [Property in keyof Type]: Type[Property];
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
type ArrayElement<ArrayType extends readonly unknown[]> = ArrayType extends readonly (infer ElementType)[]
|
|
10
|
+
? ElementType
|
|
11
|
+
: never;
|
|
12
|
+
|
|
13
|
+
// from https://gist.github.com/egardner/efd34f270cc33db67c0246e837689cb9
|
|
14
|
+
function deepEqual(obj1: any, obj2: any): boolean {
|
|
15
|
+
// Private
|
|
16
|
+
function isObject(obj: any) {
|
|
17
|
+
if (typeof obj === 'object' && obj != null) {
|
|
18
|
+
return true;
|
|
19
|
+
} else {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (obj1 === obj2) {
|
|
25
|
+
return true;
|
|
26
|
+
} else if (isObject(obj1) && isObject(obj2)) {
|
|
27
|
+
if (Object.keys(obj1).length !== Object.keys(obj2).length) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
for (var prop in obj1) {
|
|
31
|
+
if (!deepEqual(obj1[prop], obj2[prop])) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function mergeDoc(values: any, mergedDevDocs: any, field: string) {
|
|
41
|
+
if (values[field]) {
|
|
42
|
+
const mergedEventDocs = (mergedDevDocs[field] = mergedDevDocs[field] || {});
|
|
43
|
+
for (const signature of Object.keys(values[field])) {
|
|
44
|
+
if (mergedEventDocs[signature] && !deepEqual(mergedEventDocs[signature], values[field][signature])) {
|
|
45
|
+
throw new Error(`Doc ${field} conflict: "${signature}" `);
|
|
46
|
+
}
|
|
47
|
+
mergedEventDocs[signature] = values[field][signature];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function mergeABIs(list: {name: string; abi: Abi}[], options?: {doNotCheckForConflicts?: boolean}) {
|
|
53
|
+
const added: Map<string, ArrayElement<Abi>> = new Map();
|
|
54
|
+
const mergedABI: CreateMutable<Abi> = [];
|
|
55
|
+
const sigJSMap: Map<`0x${string}`, {index: number; routeName: string; functionName: string}> = new Map();
|
|
56
|
+
for (let i = 0; i < list.length; i++) {
|
|
57
|
+
const listElem = list[i];
|
|
58
|
+
for (const element of listElem.abi) {
|
|
59
|
+
if (element.type === 'function') {
|
|
60
|
+
// const selector = getFunctionSelector(element);
|
|
61
|
+
const selector = toFunctionSelector(element);
|
|
62
|
+
if (sigJSMap.has(selector)) {
|
|
63
|
+
if (!options?.doNotCheckForConflicts) {
|
|
64
|
+
const existing = sigJSMap.get(selector);
|
|
65
|
+
throw new Error(
|
|
66
|
+
`ABI conflict: ${existing!.routeName} has function "${existing!.functionName}" which conflict with ${
|
|
67
|
+
listElem.name
|
|
68
|
+
}'s "${element.name}" (selector: "${selector}") `,
|
|
69
|
+
);
|
|
70
|
+
} else {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
sigJSMap.set(selector, {index: i, routeName: listElem.name, functionName: element.name});
|
|
75
|
+
|
|
76
|
+
const exists = added.has(element.name);
|
|
77
|
+
if (exists) {
|
|
78
|
+
// TODO check if same
|
|
79
|
+
} else {
|
|
80
|
+
added.set(element.name, element);
|
|
81
|
+
mergedABI.push(element);
|
|
82
|
+
}
|
|
83
|
+
} else if (element.type === 'constructor') {
|
|
84
|
+
// we skip it
|
|
85
|
+
} else if (element.type === 'error') {
|
|
86
|
+
const exists = added.has(element.name);
|
|
87
|
+
if (exists) {
|
|
88
|
+
// TODO check if same
|
|
89
|
+
} else {
|
|
90
|
+
added.set(element.name, element);
|
|
91
|
+
mergedABI.push(element);
|
|
92
|
+
}
|
|
93
|
+
} else if (element.type === 'event') {
|
|
94
|
+
const exists = added.has(element.name);
|
|
95
|
+
if (exists) {
|
|
96
|
+
// TODO check if same
|
|
97
|
+
} else {
|
|
98
|
+
added.set(element.name, element);
|
|
99
|
+
mergedABI.push(element);
|
|
100
|
+
}
|
|
101
|
+
} else if (element.type === 'fallback') {
|
|
102
|
+
} else if (element.type === 'receive') {
|
|
103
|
+
} else {
|
|
104
|
+
// if ('name' in element) {
|
|
105
|
+
// const exists = added.has(element.name);
|
|
106
|
+
// if (exists) {
|
|
107
|
+
// // TODO check if same
|
|
108
|
+
// } else {
|
|
109
|
+
// added.set(element.name, element);
|
|
110
|
+
// mergedABI.push(element);
|
|
111
|
+
// }
|
|
112
|
+
// }
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
mergedABI,
|
|
119
|
+
added,
|
|
120
|
+
sigJSMap,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export function mergeArtifacts(
|
|
125
|
+
list: {name: string; artifact: Partial<Artifact<Abi>> & {abi: Abi}}[],
|
|
126
|
+
options?: {doNotCheckForConflicts?: boolean},
|
|
127
|
+
) {
|
|
128
|
+
const {mergedABI, added, sigJSMap} = mergeABIs(
|
|
129
|
+
list.map((v) => ({name: v.name, abi: v.artifact.abi})),
|
|
130
|
+
options,
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
const mergedDevDocs: CreateMutable<DevDoc> = {kind: 'dev', version: 1, methods: {}};
|
|
134
|
+
const mergedUserDocs: CreateMutable<UserDoc> = {kind: 'user', version: 1, methods: {}};
|
|
135
|
+
|
|
136
|
+
for (let i = 0; i < list.length; i++) {
|
|
137
|
+
const listElem = list[i];
|
|
138
|
+
|
|
139
|
+
const devdoc = listElem.artifact.devdoc;
|
|
140
|
+
if (devdoc) {
|
|
141
|
+
mergeDoc(devdoc, mergedDevDocs, 'events');
|
|
142
|
+
mergeDoc(devdoc, mergedDevDocs, 'errors');
|
|
143
|
+
mergeDoc(devdoc, mergedDevDocs, 'methods');
|
|
144
|
+
if (devdoc.author) {
|
|
145
|
+
if (mergedDevDocs.author && mergedDevDocs.author != devdoc.author) {
|
|
146
|
+
throw new Error(`DevDoc author conflict `);
|
|
147
|
+
}
|
|
148
|
+
mergedDevDocs.author = devdoc.author;
|
|
149
|
+
if (mergedDevDocs.title && mergedDevDocs.title != devdoc.title) {
|
|
150
|
+
throw new Error(`DevDoc title conflict `);
|
|
151
|
+
}
|
|
152
|
+
mergedDevDocs.title = devdoc.title;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const userdoc = listElem.artifact.userdoc;
|
|
157
|
+
if (userdoc) {
|
|
158
|
+
mergeDoc(userdoc, mergedUserDocs, 'events');
|
|
159
|
+
mergeDoc(userdoc, mergedUserDocs, 'errors');
|
|
160
|
+
mergeDoc(userdoc, mergedUserDocs, 'methods');
|
|
161
|
+
if (userdoc.notice) {
|
|
162
|
+
if (mergedUserDocs.notice && mergedUserDocs.notice != userdoc.notice) {
|
|
163
|
+
throw new Error(`UserDoc notice conflict `);
|
|
164
|
+
}
|
|
165
|
+
mergedUserDocs.notice = userdoc.notice;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return {
|
|
170
|
+
mergedABI,
|
|
171
|
+
added,
|
|
172
|
+
mergedDevDocs,
|
|
173
|
+
mergedUserDocs,
|
|
174
|
+
sigJSMap,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EnhancedEnvironment,
|
|
3
|
+
Environment,
|
|
4
|
+
UnknownDeployments,
|
|
5
|
+
UnresolvedNetworkSpecificData,
|
|
6
|
+
UnresolvedUnknownNamedAccounts,
|
|
7
|
+
CurriedFunctions,
|
|
8
|
+
} from './types.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param env - The environment object to inject as the first parameter
|
|
12
|
+
* @param functionsAndGetters - An object containing functions that expect the environment as their first parameter,
|
|
13
|
+
* or getter functions that return a value from the environment
|
|
14
|
+
* @returns An object with the same function/property names, but with the environment parameter removed
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* const functionsAndGetters = {
|
|
19
|
+
* // Functions that expect env as first parameter
|
|
20
|
+
* deploy: (env: Environment, contractName: string, args: any[]) => Promise<void>,
|
|
21
|
+
* verify: (env: Environment, address: string) => Promise<boolean>,
|
|
22
|
+
*
|
|
23
|
+
* // Getter properties that can be accessed directly
|
|
24
|
+
* myValue: (env: Environment) => env.someValue,
|
|
25
|
+
* networkId: (env: Environment) => env.network.id
|
|
26
|
+
* };
|
|
27
|
+
*
|
|
28
|
+
* const enhancedEnv = withEnvironment(env, functionsAndGetters);
|
|
29
|
+
*
|
|
30
|
+
* // Now you can call functions without passing env:
|
|
31
|
+
* await enhancedEnv.deploy('MyContract', []);
|
|
32
|
+
* await enhancedEnv.verify('0x123...');
|
|
33
|
+
*
|
|
34
|
+
* // And access getter properties directly:
|
|
35
|
+
* console.log(enhancedEnv.myValue);
|
|
36
|
+
* console.log(enhancedEnv.networkId);
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export function withEnvironment<
|
|
40
|
+
NamedAccounts extends UnresolvedUnknownNamedAccounts = UnresolvedUnknownNamedAccounts,
|
|
41
|
+
Data extends UnresolvedNetworkSpecificData = UnresolvedNetworkSpecificData,
|
|
42
|
+
Deployments extends UnknownDeployments = UnknownDeployments,
|
|
43
|
+
Extra extends Record<string, unknown> = Record<string, unknown>,
|
|
44
|
+
T extends Record<
|
|
45
|
+
string,
|
|
46
|
+
| ((env: Environment<NamedAccounts, Data, Deployments, Extra>) => (...args: any[]) => any)
|
|
47
|
+
| ((env: Environment<NamedAccounts, Data, Deployments, Extra>) => any)
|
|
48
|
+
> = Record<
|
|
49
|
+
string,
|
|
50
|
+
| ((env: Environment<NamedAccounts, Data, Deployments>) => (...args: any[]) => any)
|
|
51
|
+
| ((env: Environment<NamedAccounts, Data, Deployments>) => any)
|
|
52
|
+
>,
|
|
53
|
+
>(env: Environment<NamedAccounts, Data, Deployments, Extra>, functionsAndGetters: T): CurriedFunctions<T> {
|
|
54
|
+
const result = {} as CurriedFunctions<T>;
|
|
55
|
+
|
|
56
|
+
for (const [key, func] of Object.entries(functionsAndGetters)) {
|
|
57
|
+
// Check if the function is a getter or a regular function
|
|
58
|
+
const value = func(env);
|
|
59
|
+
|
|
60
|
+
if (typeof value === 'function') {
|
|
61
|
+
// Regular function case: Create a function that automatically passes the environment
|
|
62
|
+
(result as any)[key] = (...args: any[]) => func(env)(...args);
|
|
63
|
+
} else {
|
|
64
|
+
// Getter case: Define property with getter that returns the value
|
|
65
|
+
Object.defineProperty(result, key, {
|
|
66
|
+
get: () => func(env),
|
|
67
|
+
enumerable: true,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function enhanceEnvIfNeeded<
|
|
76
|
+
Extensions extends Record<string, (env: Environment<any, any, any>) => any> = {},
|
|
77
|
+
NamedAccounts extends UnresolvedUnknownNamedAccounts = UnresolvedUnknownNamedAccounts,
|
|
78
|
+
Data extends UnresolvedNetworkSpecificData = UnresolvedNetworkSpecificData,
|
|
79
|
+
Extra extends Record<string, unknown> = Record<string, unknown>,
|
|
80
|
+
>(
|
|
81
|
+
env: Environment,
|
|
82
|
+
extensions: Extensions,
|
|
83
|
+
): EnhancedEnvironment<NamedAccounts, Data, UnknownDeployments, Extensions, Extra> {
|
|
84
|
+
// Use the original env object as the base
|
|
85
|
+
const enhancedEnv = env as EnhancedEnvironment<NamedAccounts, Data, UnknownDeployments, Extensions, Extra>;
|
|
86
|
+
|
|
87
|
+
// Only create curried functions for extensions not already present in env
|
|
88
|
+
for (const key in extensions) {
|
|
89
|
+
if (!Object.prototype.hasOwnProperty.call(env, key)) {
|
|
90
|
+
// Create curried function only for this specific extension
|
|
91
|
+
const singleExtension: Record<string, unknown> = {};
|
|
92
|
+
singleExtension[key] = (extensions as any)[key];
|
|
93
|
+
const curriedFunction = withEnvironment(env, singleExtension as any);
|
|
94
|
+
(enhancedEnv as any)[key] = (curriedFunction as any)[key];
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return enhancedEnv;
|
|
98
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Re-export types
|
|
2
|
+
export type * from './types.js';
|
|
3
|
+
|
|
4
|
+
// Re-export JSON utilities
|
|
5
|
+
export {
|
|
6
|
+
postfixBigIntReplacer,
|
|
7
|
+
bigIntToStringReplacer,
|
|
8
|
+
postfixBigIntReviver,
|
|
9
|
+
JSONToString,
|
|
10
|
+
stringToJSON,
|
|
11
|
+
toJSONCompatibleLinkedData,
|
|
12
|
+
} from './json.js';
|
|
13
|
+
|
|
14
|
+
// Re-export artifact utilities
|
|
15
|
+
export {mergeABIs, mergeArtifacts} from './artifacts.js';
|
|
16
|
+
|
|
17
|
+
// Re-export environment utilities
|
|
18
|
+
export {withEnvironment, enhanceEnvIfNeeded} from './environment.js';
|
|
19
|
+
|
|
20
|
+
// Re-export providers
|
|
21
|
+
export {TransactionHashTrackerProvider, type TransactionHashTracker} from './providers/index.js';
|
|
22
|
+
|
|
23
|
+
// Re-export account utilities
|
|
24
|
+
export {resolveAccount, resolveAccountOrUndefined} from './account.js';
|
package/src/json.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type {LinkedDataProvided, LinkedData, JSONType, JSONTypePlusBigInt} from './types.js';
|
|
2
|
+
|
|
3
|
+
// TODO share with db-utils
|
|
4
|
+
export function postfixBigIntReplacer(k: string, v: any): any {
|
|
5
|
+
if (typeof v === 'bigint') {
|
|
6
|
+
return v.toString() + 'n';
|
|
7
|
+
}
|
|
8
|
+
return v;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function bigIntToStringReplacer(k: string, v: any): any {
|
|
12
|
+
if (typeof v === 'bigint') {
|
|
13
|
+
return v.toString();
|
|
14
|
+
}
|
|
15
|
+
return v;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function postfixBigIntReviver(k: string, v: any): any {
|
|
19
|
+
if (
|
|
20
|
+
typeof v === 'string' &&
|
|
21
|
+
(v.startsWith('-') ? !isNaN(parseInt(v.charAt(1))) : !isNaN(parseInt(v.charAt(0)))) &&
|
|
22
|
+
v.charAt(v.length - 1) === 'n'
|
|
23
|
+
) {
|
|
24
|
+
return BigInt(v.slice(0, -1));
|
|
25
|
+
}
|
|
26
|
+
return v;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function JSONToString<T = unknown>(json: unknown, space?: string | number) {
|
|
30
|
+
return JSON.stringify(json, bigIntToStringReplacer, space);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function stringToJSON<T = unknown>(str: string): T {
|
|
34
|
+
return JSON.parse(str);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Convert a LinkedDataProvided object into LinkedData by turning every
|
|
39
|
+
* bigint into its string representation (recursively).
|
|
40
|
+
*/
|
|
41
|
+
export function toJSONCompatibleLinkedData(input: LinkedDataProvided | undefined): LinkedData | undefined {
|
|
42
|
+
if (!input) {
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
return Object.fromEntries(Object.entries(input).map(([k, v]) => [k, walk(v)]));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/* ---------- internal helpers ---------- */
|
|
49
|
+
|
|
50
|
+
function walk(node: JSONTypePlusBigInt): JSONType {
|
|
51
|
+
if (typeof node === 'bigint') return node.toString();
|
|
52
|
+
|
|
53
|
+
if (Array.isArray(node)) return node.map(walk);
|
|
54
|
+
|
|
55
|
+
if (node && typeof node === 'object') {
|
|
56
|
+
const out: Record<string, JSONType> = {};
|
|
57
|
+
for (const [k, v] of Object.entries(node)) out[k] = walk(v);
|
|
58
|
+
return out;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/* string | number | boolean | null */
|
|
62
|
+
return node;
|
|
63
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import {EIP1193GenericRequest, EIP1193GenericRequestProvider, EIP1193ProviderWithoutEvents} from 'eip-1193';
|
|
2
|
+
|
|
3
|
+
export abstract class BaseProvider implements EIP1193ProviderWithoutEvents {
|
|
4
|
+
constructor(protected provider: EIP1193ProviderWithoutEvents) {}
|
|
5
|
+
|
|
6
|
+
request(args: any): Promise<any> {
|
|
7
|
+
return this._request(args);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
protected abstract _request<T = unknown, V extends EIP1193GenericRequest = EIP1193GenericRequest>(
|
|
11
|
+
args: V,
|
|
12
|
+
): Promise<T>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type {EIP1193GenericRequest, EIP1193ProviderWithoutEvents} from 'eip-1193';
|
|
2
|
+
import {BaseProvider} from './BaseProvider.js';
|
|
3
|
+
import {logs} from 'named-logs';
|
|
4
|
+
|
|
5
|
+
const console = logs('rocketh-provider');
|
|
6
|
+
|
|
7
|
+
export class TransactionHashTrackerProvider extends BaseProvider implements EIP1193ProviderWithoutEvents {
|
|
8
|
+
public transactionHashes: `0x${string}`[] = [];
|
|
9
|
+
|
|
10
|
+
constructor(provider: EIP1193ProviderWithoutEvents) {
|
|
11
|
+
super(provider);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
protected async _request<T = unknown, V extends EIP1193GenericRequest = EIP1193GenericRequest>(args: V): Promise<T> {
|
|
15
|
+
console.debug(`calling ${args.method} with ${args.params?.length || 0} arguments`);
|
|
16
|
+
const response = await this.provider.request(args as any);
|
|
17
|
+
if (args.method === 'eth_sendRawTransaction' || args.method === 'eth_sendTransaction') {
|
|
18
|
+
this.transactionHashes.push(response as `0x${string}`);
|
|
19
|
+
}
|
|
20
|
+
return response as T;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type TransactionHashTracker = EIP1193ProviderWithoutEvents & {
|
|
25
|
+
transactionHashes: `0x${string}`[];
|
|
26
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './TransactionHashTracker.js';
|