permissionless 0.1.21 → 0.1.23
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/CHANGELOG.md +12 -0
- package/_cjs/accounts/index.js +5 -1
- package/_cjs/accounts/index.js.map +1 -1
- package/_cjs/accounts/kernel/signerToEcdsaKernelSmartAccount.js +6 -0
- package/_cjs/accounts/kernel/signerToEcdsaKernelSmartAccount.js.map +1 -1
- package/_cjs/accounts/light/privateKeyToLightSmartAccount.js +14 -0
- package/_cjs/accounts/light/privateKeyToLightSmartAccount.js.map +1 -0
- package/_cjs/accounts/light/signerToLightSmartAccount.js +255 -0
- package/_cjs/accounts/light/signerToLightSmartAccount.js.map +1 -0
- package/_cjs/actions/bundler/getUserOperationReceipt.js +3 -0
- package/_cjs/actions/bundler/getUserOperationReceipt.js.map +1 -1
- package/_esm/accounts/index.js +3 -1
- package/_esm/accounts/index.js.map +1 -1
- package/_esm/accounts/kernel/signerToEcdsaKernelSmartAccount.js +6 -0
- package/_esm/accounts/kernel/signerToEcdsaKernelSmartAccount.js.map +1 -1
- package/_esm/accounts/light/privateKeyToLightSmartAccount.js +16 -0
- package/_esm/accounts/light/privateKeyToLightSmartAccount.js.map +1 -0
- package/_esm/accounts/light/signerToLightSmartAccount.js +257 -0
- package/_esm/accounts/light/signerToLightSmartAccount.js.map +1 -0
- package/_esm/actions/bundler/getUserOperationReceipt.js +3 -0
- package/_esm/actions/bundler/getUserOperationReceipt.js.map +1 -1
- package/_types/accounts/index.d.ts +3 -1
- package/_types/accounts/index.d.ts.map +1 -1
- package/_types/accounts/kernel/signerToEcdsaKernelSmartAccount.d.ts.map +1 -1
- package/_types/accounts/light/privateKeyToLightSmartAccount.d.ts +13 -0
- package/_types/accounts/light/privateKeyToLightSmartAccount.d.ts.map +1 -0
- package/_types/accounts/light/signerToLightSmartAccount.d.ts +21 -0
- package/_types/accounts/light/signerToLightSmartAccount.d.ts.map +1 -0
- package/_types/actions/bundler/getUserOperationReceipt.d.ts +3 -0
- package/_types/actions/bundler/getUserOperationReceipt.d.ts.map +1 -1
- package/_types/types/bundler.d.ts +3 -0
- package/_types/types/bundler.d.ts.map +1 -1
- package/accounts/index.ts +16 -0
- package/accounts/kernel/signerToEcdsaKernelSmartAccount.ts +9 -0
- package/accounts/light/privateKeyToLightSmartAccount.ts +37 -0
- package/accounts/light/signerToLightSmartAccount.ts +407 -0
- package/actions/bundler/getUserOperationReceipt.ts +6 -0
- package/package.json +1 -1
- package/types/bundler.ts +3 -0
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type Address,
|
|
3
|
+
type Chain,
|
|
4
|
+
type Client,
|
|
5
|
+
type Hex,
|
|
6
|
+
type LocalAccount,
|
|
7
|
+
type Transport,
|
|
8
|
+
type TypedData,
|
|
9
|
+
type TypedDataDefinition,
|
|
10
|
+
concatHex,
|
|
11
|
+
encodeFunctionData,
|
|
12
|
+
hashMessage,
|
|
13
|
+
hashTypedData
|
|
14
|
+
} from "viem"
|
|
15
|
+
import { getChainId, signMessage } from "viem/actions"
|
|
16
|
+
import { getAccountNonce } from "../../actions/public/getAccountNonce"
|
|
17
|
+
import { getSenderAddress } from "../../actions/public/getSenderAddress"
|
|
18
|
+
import type {
|
|
19
|
+
ENTRYPOINT_ADDRESS_V06_TYPE,
|
|
20
|
+
ENTRYPOINT_ADDRESS_V07_TYPE,
|
|
21
|
+
Prettify
|
|
22
|
+
} from "../../types"
|
|
23
|
+
import type { EntryPoint } from "../../types/entrypoint"
|
|
24
|
+
import { getEntryPointVersion } from "../../utils"
|
|
25
|
+
import { getUserOperationHash } from "../../utils/getUserOperationHash"
|
|
26
|
+
import { isSmartAccountDeployed } from "../../utils/isSmartAccountDeployed"
|
|
27
|
+
import { toSmartAccount } from "../toSmartAccount"
|
|
28
|
+
import {
|
|
29
|
+
SignTransactionNotSupportedBySmartAccount,
|
|
30
|
+
type SmartAccount,
|
|
31
|
+
type SmartAccountSigner
|
|
32
|
+
} from "../types"
|
|
33
|
+
|
|
34
|
+
export type LightSmartAccount<
|
|
35
|
+
entryPoint extends EntryPoint,
|
|
36
|
+
transport extends Transport = Transport,
|
|
37
|
+
chain extends Chain | undefined = Chain | undefined
|
|
38
|
+
> = SmartAccount<entryPoint, "LightSmartAccount", transport, chain>
|
|
39
|
+
|
|
40
|
+
const getAccountInitCode = async (
|
|
41
|
+
owner: Address,
|
|
42
|
+
index = BigInt(0)
|
|
43
|
+
): Promise<Hex> => {
|
|
44
|
+
if (!owner) throw new Error("Owner account not found")
|
|
45
|
+
|
|
46
|
+
return encodeFunctionData({
|
|
47
|
+
abi: [
|
|
48
|
+
{
|
|
49
|
+
inputs: [
|
|
50
|
+
{
|
|
51
|
+
internalType: "address",
|
|
52
|
+
name: "owner",
|
|
53
|
+
type: "address"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
internalType: "uint256",
|
|
57
|
+
name: "salt",
|
|
58
|
+
type: "uint256"
|
|
59
|
+
}
|
|
60
|
+
],
|
|
61
|
+
name: "createAccount",
|
|
62
|
+
outputs: [
|
|
63
|
+
{
|
|
64
|
+
internalType: "contract LightAccount",
|
|
65
|
+
name: "ret",
|
|
66
|
+
type: "address"
|
|
67
|
+
}
|
|
68
|
+
],
|
|
69
|
+
stateMutability: "nonpayable",
|
|
70
|
+
type: "function"
|
|
71
|
+
}
|
|
72
|
+
],
|
|
73
|
+
functionName: "createAccount",
|
|
74
|
+
args: [owner, index]
|
|
75
|
+
})
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const getAccountAddress = async <
|
|
79
|
+
entryPoint extends EntryPoint,
|
|
80
|
+
TTransport extends Transport = Transport,
|
|
81
|
+
TChain extends Chain | undefined = Chain | undefined
|
|
82
|
+
>({
|
|
83
|
+
client,
|
|
84
|
+
factoryAddress,
|
|
85
|
+
entryPoint: entryPointAddress,
|
|
86
|
+
owner,
|
|
87
|
+
index = BigInt(0)
|
|
88
|
+
}: {
|
|
89
|
+
client: Client<TTransport, TChain>
|
|
90
|
+
factoryAddress: Address
|
|
91
|
+
owner: Address
|
|
92
|
+
entryPoint: entryPoint
|
|
93
|
+
index?: bigint
|
|
94
|
+
}): Promise<Address> => {
|
|
95
|
+
const entryPointVersion = getEntryPointVersion(entryPointAddress)
|
|
96
|
+
|
|
97
|
+
const factoryData = await getAccountInitCode(owner, index)
|
|
98
|
+
|
|
99
|
+
if (entryPointVersion === "v0.6") {
|
|
100
|
+
return getSenderAddress<ENTRYPOINT_ADDRESS_V06_TYPE>(client, {
|
|
101
|
+
initCode: concatHex([factoryAddress, factoryData]),
|
|
102
|
+
entryPoint: entryPointAddress as ENTRYPOINT_ADDRESS_V06_TYPE
|
|
103
|
+
})
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Get the sender address based on the init code
|
|
107
|
+
return getSenderAddress<ENTRYPOINT_ADDRESS_V07_TYPE>(client, {
|
|
108
|
+
factory: factoryAddress,
|
|
109
|
+
factoryData,
|
|
110
|
+
entryPoint: entryPointAddress as ENTRYPOINT_ADDRESS_V07_TYPE
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export type LightVersion = "v1.1.0"
|
|
115
|
+
|
|
116
|
+
export type SignerToLightSmartAccountParameters<
|
|
117
|
+
entryPoint extends EntryPoint,
|
|
118
|
+
TSource extends string = string,
|
|
119
|
+
TAddress extends Address = Address
|
|
120
|
+
> = Prettify<{
|
|
121
|
+
signer: SmartAccountSigner<TSource, TAddress>
|
|
122
|
+
lightVersion: LightVersion
|
|
123
|
+
entryPoint: entryPoint
|
|
124
|
+
factoryAddress?: Address
|
|
125
|
+
index?: bigint
|
|
126
|
+
address?: Address
|
|
127
|
+
}>
|
|
128
|
+
|
|
129
|
+
async function signWith1271WrapperV1<
|
|
130
|
+
TSource extends string = string,
|
|
131
|
+
TAddress extends Address = Address
|
|
132
|
+
>(
|
|
133
|
+
signer: SmartAccountSigner<TSource, TAddress>,
|
|
134
|
+
chainId: number,
|
|
135
|
+
accountAddress: Address,
|
|
136
|
+
hashedMessage: Hex
|
|
137
|
+
): Promise<Hex> {
|
|
138
|
+
return signer.signTypedData({
|
|
139
|
+
domain: {
|
|
140
|
+
chainId: Number(chainId),
|
|
141
|
+
name: "LightAccount",
|
|
142
|
+
verifyingContract: accountAddress,
|
|
143
|
+
version: "1"
|
|
144
|
+
},
|
|
145
|
+
types: {
|
|
146
|
+
LightAccountMessage: [{ name: "message", type: "bytes" }]
|
|
147
|
+
},
|
|
148
|
+
message: {
|
|
149
|
+
message: hashedMessage
|
|
150
|
+
},
|
|
151
|
+
primaryType: "LightAccountMessage"
|
|
152
|
+
})
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const LIGHT_VERSION_TO_ADDRESSES_MAP: {
|
|
156
|
+
[key in LightVersion]: {
|
|
157
|
+
factoryAddress: Address
|
|
158
|
+
}
|
|
159
|
+
} = {
|
|
160
|
+
"v1.1.0": {
|
|
161
|
+
factoryAddress: "0x00004EC70002a32400f8ae005A26081065620D20"
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const getDefaultAddresses = (
|
|
166
|
+
lightVersion: LightVersion,
|
|
167
|
+
{
|
|
168
|
+
factoryAddress: _factoryAddress
|
|
169
|
+
}: {
|
|
170
|
+
factoryAddress?: Address
|
|
171
|
+
}
|
|
172
|
+
) => {
|
|
173
|
+
const factoryAddress =
|
|
174
|
+
_factoryAddress ??
|
|
175
|
+
LIGHT_VERSION_TO_ADDRESSES_MAP[lightVersion].factoryAddress
|
|
176
|
+
|
|
177
|
+
return {
|
|
178
|
+
factoryAddress
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* @description Creates an Light Account from a private key.
|
|
184
|
+
*
|
|
185
|
+
* @returns A Private Key Light Account.
|
|
186
|
+
*/
|
|
187
|
+
export async function signerToLightSmartAccount<
|
|
188
|
+
entryPoint extends EntryPoint,
|
|
189
|
+
TTransport extends Transport = Transport,
|
|
190
|
+
TChain extends Chain | undefined = Chain | undefined,
|
|
191
|
+
TSource extends string = string,
|
|
192
|
+
TAddress extends Address = Address
|
|
193
|
+
>(
|
|
194
|
+
client: Client<TTransport, TChain, undefined>,
|
|
195
|
+
{
|
|
196
|
+
signer,
|
|
197
|
+
address,
|
|
198
|
+
lightVersion,
|
|
199
|
+
entryPoint: entryPointAddress,
|
|
200
|
+
index = BigInt(0),
|
|
201
|
+
factoryAddress: _factoryAddress
|
|
202
|
+
}: SignerToLightSmartAccountParameters<entryPoint, TSource, TAddress>
|
|
203
|
+
): Promise<LightSmartAccount<entryPoint, TTransport, TChain>> {
|
|
204
|
+
const viemSigner: LocalAccount = {
|
|
205
|
+
...signer,
|
|
206
|
+
signTransaction: (_, __) => {
|
|
207
|
+
throw new SignTransactionNotSupportedBySmartAccount()
|
|
208
|
+
}
|
|
209
|
+
} as LocalAccount
|
|
210
|
+
|
|
211
|
+
if (lightVersion !== "v1.1.0") {
|
|
212
|
+
throw new Error(
|
|
213
|
+
"Only Light Account version v1.1.0 is supported at the moment"
|
|
214
|
+
)
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const { factoryAddress } = getDefaultAddresses(lightVersion, {
|
|
218
|
+
factoryAddress: _factoryAddress
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
const [accountAddress, chainId] = await Promise.all([
|
|
222
|
+
address ??
|
|
223
|
+
getAccountAddress<entryPoint, TTransport, TChain>({
|
|
224
|
+
client,
|
|
225
|
+
factoryAddress,
|
|
226
|
+
entryPoint: entryPointAddress,
|
|
227
|
+
owner: viemSigner.address,
|
|
228
|
+
index
|
|
229
|
+
}),
|
|
230
|
+
client.chain?.id ?? getChainId(client)
|
|
231
|
+
])
|
|
232
|
+
|
|
233
|
+
if (!accountAddress) throw new Error("Account address not found")
|
|
234
|
+
|
|
235
|
+
let smartAccountDeployed = await isSmartAccountDeployed(
|
|
236
|
+
client,
|
|
237
|
+
accountAddress
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
return toSmartAccount({
|
|
241
|
+
address: accountAddress,
|
|
242
|
+
signMessage: async ({ message }) => {
|
|
243
|
+
return signWith1271WrapperV1<TSource, TAddress>(
|
|
244
|
+
signer,
|
|
245
|
+
chainId,
|
|
246
|
+
accountAddress,
|
|
247
|
+
hashMessage(message)
|
|
248
|
+
)
|
|
249
|
+
},
|
|
250
|
+
signTransaction: (_, __) => {
|
|
251
|
+
throw new SignTransactionNotSupportedBySmartAccount()
|
|
252
|
+
},
|
|
253
|
+
async signTypedData<
|
|
254
|
+
const TTypedData extends TypedData | Record<string, unknown>,
|
|
255
|
+
TPrimaryType extends
|
|
256
|
+
| keyof TTypedData
|
|
257
|
+
| "EIP712Domain" = keyof TTypedData
|
|
258
|
+
>(typedData: TypedDataDefinition<TTypedData, TPrimaryType>) {
|
|
259
|
+
return signWith1271WrapperV1<TSource, TAddress>(
|
|
260
|
+
signer,
|
|
261
|
+
chainId,
|
|
262
|
+
accountAddress,
|
|
263
|
+
hashTypedData(typedData)
|
|
264
|
+
)
|
|
265
|
+
},
|
|
266
|
+
client: client,
|
|
267
|
+
publicKey: accountAddress,
|
|
268
|
+
entryPoint: entryPointAddress,
|
|
269
|
+
source: "LightSmartAccount",
|
|
270
|
+
async getNonce() {
|
|
271
|
+
return getAccountNonce(client, {
|
|
272
|
+
sender: accountAddress,
|
|
273
|
+
entryPoint: entryPointAddress
|
|
274
|
+
})
|
|
275
|
+
},
|
|
276
|
+
async signUserOperation(userOperation) {
|
|
277
|
+
return signMessage(client, {
|
|
278
|
+
account: viemSigner,
|
|
279
|
+
message: {
|
|
280
|
+
raw: getUserOperationHash({
|
|
281
|
+
userOperation,
|
|
282
|
+
entryPoint: entryPointAddress,
|
|
283
|
+
chainId: chainId
|
|
284
|
+
})
|
|
285
|
+
}
|
|
286
|
+
})
|
|
287
|
+
},
|
|
288
|
+
async getInitCode() {
|
|
289
|
+
if (smartAccountDeployed) return "0x"
|
|
290
|
+
|
|
291
|
+
smartAccountDeployed = await isSmartAccountDeployed(
|
|
292
|
+
client,
|
|
293
|
+
accountAddress
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
if (smartAccountDeployed) return "0x"
|
|
297
|
+
|
|
298
|
+
return concatHex([
|
|
299
|
+
factoryAddress,
|
|
300
|
+
await getAccountInitCode(viemSigner.address, index)
|
|
301
|
+
])
|
|
302
|
+
},
|
|
303
|
+
async getFactory() {
|
|
304
|
+
if (smartAccountDeployed) return undefined
|
|
305
|
+
smartAccountDeployed = await isSmartAccountDeployed(
|
|
306
|
+
client,
|
|
307
|
+
accountAddress
|
|
308
|
+
)
|
|
309
|
+
if (smartAccountDeployed) return undefined
|
|
310
|
+
return factoryAddress
|
|
311
|
+
},
|
|
312
|
+
async getFactoryData() {
|
|
313
|
+
if (smartAccountDeployed) return undefined
|
|
314
|
+
smartAccountDeployed = await isSmartAccountDeployed(
|
|
315
|
+
client,
|
|
316
|
+
accountAddress
|
|
317
|
+
)
|
|
318
|
+
if (smartAccountDeployed) return undefined
|
|
319
|
+
return getAccountInitCode(viemSigner.address, index)
|
|
320
|
+
},
|
|
321
|
+
async encodeDeployCallData(_) {
|
|
322
|
+
throw new Error("Light account doesn't support account deployment")
|
|
323
|
+
},
|
|
324
|
+
async encodeCallData(args) {
|
|
325
|
+
if (Array.isArray(args)) {
|
|
326
|
+
const argsArray = args as {
|
|
327
|
+
to: Address
|
|
328
|
+
value: bigint
|
|
329
|
+
data: Hex
|
|
330
|
+
}[]
|
|
331
|
+
|
|
332
|
+
return encodeFunctionData({
|
|
333
|
+
abi: [
|
|
334
|
+
{
|
|
335
|
+
inputs: [
|
|
336
|
+
{
|
|
337
|
+
internalType: "address[]",
|
|
338
|
+
name: "dest",
|
|
339
|
+
type: "address[]"
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
internalType: "uint256[]",
|
|
343
|
+
name: "value",
|
|
344
|
+
type: "uint256[]"
|
|
345
|
+
},
|
|
346
|
+
{
|
|
347
|
+
internalType: "bytes[]",
|
|
348
|
+
name: "func",
|
|
349
|
+
type: "bytes[]"
|
|
350
|
+
}
|
|
351
|
+
],
|
|
352
|
+
name: "executeBatch",
|
|
353
|
+
outputs: [],
|
|
354
|
+
stateMutability: "nonpayable",
|
|
355
|
+
type: "function"
|
|
356
|
+
}
|
|
357
|
+
],
|
|
358
|
+
functionName: "executeBatch",
|
|
359
|
+
args: [
|
|
360
|
+
argsArray.map((a) => a.to),
|
|
361
|
+
argsArray.map((a) => a.value),
|
|
362
|
+
argsArray.map((a) => a.data)
|
|
363
|
+
]
|
|
364
|
+
})
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
const { to, value, data } = args as {
|
|
368
|
+
to: Address
|
|
369
|
+
value: bigint
|
|
370
|
+
data: Hex
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
return encodeFunctionData({
|
|
374
|
+
abi: [
|
|
375
|
+
{
|
|
376
|
+
inputs: [
|
|
377
|
+
{
|
|
378
|
+
internalType: "address",
|
|
379
|
+
name: "dest",
|
|
380
|
+
type: "address"
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
internalType: "uint256",
|
|
384
|
+
name: "value",
|
|
385
|
+
type: "uint256"
|
|
386
|
+
},
|
|
387
|
+
{
|
|
388
|
+
internalType: "bytes",
|
|
389
|
+
name: "func",
|
|
390
|
+
type: "bytes"
|
|
391
|
+
}
|
|
392
|
+
],
|
|
393
|
+
name: "execute",
|
|
394
|
+
outputs: [],
|
|
395
|
+
stateMutability: "nonpayable",
|
|
396
|
+
type: "function"
|
|
397
|
+
}
|
|
398
|
+
],
|
|
399
|
+
functionName: "execute",
|
|
400
|
+
args: [to, value, data]
|
|
401
|
+
})
|
|
402
|
+
},
|
|
403
|
+
async getDummySignature(_userOperation) {
|
|
404
|
+
return "0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c"
|
|
405
|
+
}
|
|
406
|
+
})
|
|
407
|
+
}
|
|
@@ -20,11 +20,14 @@ export type GetUserOperationReceiptParameters = {
|
|
|
20
20
|
|
|
21
21
|
export type GetUserOperationReceiptReturnType = {
|
|
22
22
|
userOpHash: Hash
|
|
23
|
+
entryPoint: Address
|
|
23
24
|
sender: Address
|
|
24
25
|
nonce: bigint
|
|
26
|
+
paymaster?: Address
|
|
25
27
|
actualGasUsed: bigint
|
|
26
28
|
actualGasCost: bigint
|
|
27
29
|
success: boolean
|
|
30
|
+
reason?: string
|
|
28
31
|
receipt: {
|
|
29
32
|
transactionHash: Hex
|
|
30
33
|
transactionIndex: bigint
|
|
@@ -93,11 +96,14 @@ export const getUserOperationReceipt = async <
|
|
|
93
96
|
|
|
94
97
|
const userOperationReceipt: GetUserOperationReceiptReturnType = {
|
|
95
98
|
userOpHash: response.userOpHash,
|
|
99
|
+
entryPoint: response.entryPoint,
|
|
96
100
|
sender: response.sender,
|
|
97
101
|
nonce: BigInt(response.nonce),
|
|
102
|
+
paymaster: response.paymaster,
|
|
98
103
|
actualGasUsed: BigInt(response.actualGasUsed),
|
|
99
104
|
actualGasCost: BigInt(response.actualGasCost),
|
|
100
105
|
success: response.success,
|
|
106
|
+
reason: response.reason,
|
|
101
107
|
receipt: {
|
|
102
108
|
transactionHash: response.receipt.transactionHash,
|
|
103
109
|
transactionIndex: BigInt(response.receipt.transactionIndex),
|
package/package.json
CHANGED
package/types/bundler.ts
CHANGED
|
@@ -81,11 +81,14 @@ export type BundlerRpcSchema<entryPoint extends EntryPoint> = [
|
|
|
81
81
|
|
|
82
82
|
type UserOperationReceiptWithBigIntAsHex = {
|
|
83
83
|
userOpHash: Hash
|
|
84
|
+
entryPoint: Address
|
|
84
85
|
sender: Address
|
|
85
86
|
nonce: Hex
|
|
87
|
+
paymaster?: Address
|
|
86
88
|
actualGasUsed: Hex
|
|
87
89
|
actualGasCost: Hex
|
|
88
90
|
success: boolean
|
|
91
|
+
reason?: string
|
|
89
92
|
receipt: {
|
|
90
93
|
transactionHash: Hex
|
|
91
94
|
transactionIndex: Hex
|