dequanto 0.2.31 → 0.2.33
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/lib/cjs/config/ConfigDefaults.js +1 -0
- package/lib/cjs/config/ConfigDefaults.js.map +1 -1
- package/lib/cjs/contracts/ContractBase.js +68 -23
- package/lib/cjs/contracts/ContractBase.js.map +1 -1
- package/lib/cjs/rpc/RpcBase.js.map +1 -1
- package/lib/cjs/safe/SafeTx.js +8 -2
- package/lib/cjs/safe/SafeTx.js.map +1 -1
- package/lib/cjs/utils/$traces.js +8 -0
- package/lib/cjs/utils/$traces.js.map +1 -1
- package/lib/esm/config/ConfigDefaults.js.map +1 -1
- package/lib/esm/config/ConfigDefaults.mjs +1 -0
- package/lib/esm/contracts/ContractBase.js.map +1 -1
- package/lib/esm/contracts/ContractBase.mjs +68 -23
- package/lib/esm/rpc/RpcBase.js.map +1 -1
- package/lib/esm/safe/SafeTx.js.map +1 -1
- package/lib/esm/safe/SafeTx.mjs +8 -2
- package/lib/esm/utils/$traces.js.map +1 -1
- package/lib/esm/utils/$traces.mjs +8 -0
- package/lib/types/config/interface/IConfigData.d.ts +1 -0
- package/package.json +1 -1
- package/src/config/ConfigDefaults.ts +1 -0
- package/src/config/interface/IConfigData.ts +1 -0
- package/src/contracts/ContractBase.ts +122 -72
- package/src/rpc/RpcBase.ts +1 -0
- package/src/safe/SafeTx.ts +9 -2
- package/src/utils/$traces.ts +13 -4
|
@@ -60,7 +60,7 @@ export abstract class ContractBase {
|
|
|
60
60
|
|
|
61
61
|
storage?: ContractStorageReaderBase
|
|
62
62
|
|
|
63
|
-
constructor
|
|
63
|
+
constructor(
|
|
64
64
|
public address: TAddress,
|
|
65
65
|
public client: Web3Client,
|
|
66
66
|
public explorer: IBlockchainExplorer
|
|
@@ -77,28 +77,28 @@ export abstract class ContractBase {
|
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
public async $getStorageAt
|
|
80
|
+
public async $getStorageAt(position: number | bigint | TEth.Hex) {
|
|
81
81
|
let reader = await this.getContractReader();
|
|
82
82
|
return reader.getStorageAt(this.address, position);
|
|
83
83
|
}
|
|
84
|
-
public $parseInputData
|
|
84
|
+
public $parseInputData(buffer: TEth.BufferLike, value?: string) {
|
|
85
85
|
return $abiUtils.parseMethodCallData(this.abi, buffer);
|
|
86
86
|
}
|
|
87
|
-
public async $executeBatch
|
|
87
|
+
public async $executeBatch<T extends readonly unknown[] | ContractReaderUtils.IContractReadParams[]>(values: T): Promise<
|
|
88
88
|
{ -readonly [P in keyof T]: ContractReaderUtils.TIContractReadParamsInferred<T[P]>; }
|
|
89
89
|
> {
|
|
90
90
|
let reader = await this.getContractReader();
|
|
91
91
|
return reader.executeBatch(values);
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
async getPastLogs
|
|
94
|
+
async getPastLogs<TEvents extends TEventsBase, TEventName extends keyof TEvents>(
|
|
95
95
|
event: TEventName | TEventName[]
|
|
96
96
|
, options?: TEventLogOptions<TEventParams<TEvents, TEventName>>
|
|
97
97
|
): Promise<ITxLogItem<TEventParams<TEvents, TEventName>, TEventName>[]> {
|
|
98
98
|
return await this.$getPastLogsParsed(event as string | string[], options) as any;
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
public $config
|
|
101
|
+
public $config(builderConfig?: ITxBuilderOptions, writerConfig?: ITxWriterOptions): this {
|
|
102
102
|
let $contract = $class.curry(this, {
|
|
103
103
|
builderConfig: {
|
|
104
104
|
...(this.builderConfig ?? {}),
|
|
@@ -119,7 +119,7 @@ export abstract class ContractBase {
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
@memd.deco.memoize({ perInstance: true })
|
|
122
|
-
public $call
|
|
122
|
+
public $call() {
|
|
123
123
|
let abiArr = this.abi;
|
|
124
124
|
let writer = this.getContractWriter();
|
|
125
125
|
|
|
@@ -127,7 +127,7 @@ export abstract class ContractBase {
|
|
|
127
127
|
let fns = alot(methods).map(abiMethod => {
|
|
128
128
|
return {
|
|
129
129
|
name: abiMethod.name,
|
|
130
|
-
async fn
|
|
130
|
+
async fn(sender: TAccount, ...args: any[]) {
|
|
131
131
|
return ContractBaseUtils.$call(
|
|
132
132
|
writer,
|
|
133
133
|
abiMethod,
|
|
@@ -146,7 +146,7 @@ export abstract class ContractBase {
|
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
@memd.deco.memoize({ perInstance: true })
|
|
149
|
-
public $data
|
|
149
|
+
public $data(params?: {
|
|
150
150
|
estimateGas?: boolean
|
|
151
151
|
getNonce?: boolean
|
|
152
152
|
from?: TAddress
|
|
@@ -160,14 +160,14 @@ export abstract class ContractBase {
|
|
|
160
160
|
let writeFns = alot(writeMethods).map(method => {
|
|
161
161
|
return {
|
|
162
162
|
name: method.name,
|
|
163
|
-
async fn
|
|
163
|
+
async fn(sender: TAccount, ...args: any[]) {
|
|
164
164
|
let writer: TxWriter = await $top
|
|
165
165
|
.$config({
|
|
166
166
|
send: 'manual',
|
|
167
167
|
gasEstimation: false,
|
|
168
168
|
nonce: params?.getNonce ? void 0 : 0,
|
|
169
169
|
})
|
|
170
|
-
|
|
170
|
+
[method.name](sender, ...args);
|
|
171
171
|
|
|
172
172
|
if (params?.getNonce) {
|
|
173
173
|
await writer.builder.ensureNonce();
|
|
@@ -192,7 +192,7 @@ export abstract class ContractBase {
|
|
|
192
192
|
let readFns = alot(readMethods).map(method => {
|
|
193
193
|
return {
|
|
194
194
|
name: method.name,
|
|
195
|
-
async fn
|
|
195
|
+
async fn(...args: any[]) {
|
|
196
196
|
return {
|
|
197
197
|
to: $top.address,
|
|
198
198
|
data: $abiUtils.serializeMethodCallData(method, args)
|
|
@@ -209,7 +209,7 @@ export abstract class ContractBase {
|
|
|
209
209
|
}
|
|
210
210
|
|
|
211
211
|
@memd.deco.memoize({ perInstance: true })
|
|
212
|
-
public $gas
|
|
212
|
+
public $gas() {
|
|
213
213
|
let abiArr = this.abi;
|
|
214
214
|
let writer = this.getContractWriter();
|
|
215
215
|
|
|
@@ -217,7 +217,7 @@ export abstract class ContractBase {
|
|
|
217
217
|
let fns = alot(methods).map(abiMethod => {
|
|
218
218
|
return {
|
|
219
219
|
name: abiMethod.name,
|
|
220
|
-
async fn
|
|
220
|
+
async fn(sender: IAccount, ...args: any[]) {
|
|
221
221
|
return ContractBaseUtils.$gas(
|
|
222
222
|
writer,
|
|
223
223
|
abiMethod,
|
|
@@ -235,11 +235,11 @@ export abstract class ContractBase {
|
|
|
235
235
|
return $contract as any;
|
|
236
236
|
}
|
|
237
237
|
|
|
238
|
-
public $req
|
|
238
|
+
public $req() {
|
|
239
239
|
return FnRequestWrapper.create(this);
|
|
240
240
|
}
|
|
241
241
|
|
|
242
|
-
public $signed
|
|
242
|
+
public $signed(builderConfig?: ITxBuilderOptions, writerConfig?: ITxWriterOptions) {
|
|
243
243
|
let instance = this.$signedCreate();
|
|
244
244
|
if (builderConfig != null || writerConfig != null) {
|
|
245
245
|
instance = instance.$config(builderConfig, writerConfig);
|
|
@@ -248,18 +248,18 @@ export abstract class ContractBase {
|
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
@memd.deco.memoize({ perInstance: true })
|
|
251
|
-
private $signedCreate
|
|
251
|
+
private $signedCreate() {
|
|
252
252
|
return FnSignedWrapper.create(this);
|
|
253
253
|
}
|
|
254
254
|
|
|
255
255
|
@memd.deco.memoize({ perInstance: true })
|
|
256
|
-
public $receipt
|
|
256
|
+
public $receipt<T extends this>(this: T): T {
|
|
257
257
|
let $top = this;
|
|
258
258
|
let methods = this.abi.filter(abi => abi.type === 'function' && $abiUtils.isReadMethod(abi) === false);
|
|
259
259
|
let fns = alot(methods).map(abiMethod => {
|
|
260
260
|
return {
|
|
261
261
|
name: abiMethod.name,
|
|
262
|
-
async fn
|
|
262
|
+
async fn(sender: IAccount, ...args: any[]) {
|
|
263
263
|
let tx: TxWriter = await $top[abiMethod.name](sender, ...args);
|
|
264
264
|
let receipt = await tx.wait();
|
|
265
265
|
return tx;
|
|
@@ -273,7 +273,7 @@ export abstract class ContractBase {
|
|
|
273
273
|
return $contract as any;
|
|
274
274
|
}
|
|
275
275
|
|
|
276
|
-
public forBlock
|
|
276
|
+
public forBlock(mix: number | bigint | undefined | Date): this {
|
|
277
277
|
if (mix == null) {
|
|
278
278
|
return this;
|
|
279
279
|
}
|
|
@@ -282,14 +282,14 @@ export abstract class ContractBase {
|
|
|
282
282
|
}
|
|
283
283
|
return this.forBlockAt(mix);
|
|
284
284
|
}
|
|
285
|
-
protected forBlockNumber
|
|
285
|
+
protected forBlockNumber(blockNumber: number | bigint | undefined): this {
|
|
286
286
|
let $contract = $class.curry(this, {
|
|
287
287
|
blockNumber: blockNumber,
|
|
288
288
|
blockDate: null
|
|
289
289
|
})
|
|
290
290
|
return $contract;
|
|
291
291
|
}
|
|
292
|
-
protected forBlockAt
|
|
292
|
+
protected forBlockAt(date: Date | undefined): this {
|
|
293
293
|
let $contract = $class.curry(this, {
|
|
294
294
|
blockNumber: null,
|
|
295
295
|
blockDate: date
|
|
@@ -297,7 +297,7 @@ export abstract class ContractBase {
|
|
|
297
297
|
return $contract;
|
|
298
298
|
}
|
|
299
299
|
|
|
300
|
-
protected $read
|
|
300
|
+
protected $read(abi: string | TAbiItem, ...params) {
|
|
301
301
|
if (this.builderConfig?.send === 'manual') {
|
|
302
302
|
let req = <ContractReaderUtils.IContractReadParams>{
|
|
303
303
|
address: this.address,
|
|
@@ -314,7 +314,7 @@ export abstract class ContractBase {
|
|
|
314
314
|
return reader.readAsync(this.address, abi, ...params);
|
|
315
315
|
}
|
|
316
316
|
|
|
317
|
-
public $onLog
|
|
317
|
+
public $onLog(event: string, cb?) {
|
|
318
318
|
let stream = this.getContractStream();
|
|
319
319
|
let events = stream.on(event);
|
|
320
320
|
if (cb) {
|
|
@@ -323,12 +323,12 @@ export abstract class ContractBase {
|
|
|
323
323
|
return events;
|
|
324
324
|
}
|
|
325
325
|
|
|
326
|
-
public $onTransaction
|
|
326
|
+
public $onTransaction(options?: BlockWalker.IBlockWalkerOptions): SubjectStream<{ tx: TEth.Tx, block: TEth.Block, calldata: { method, arguments: any[] } }> {
|
|
327
327
|
|
|
328
328
|
options ??= {};
|
|
329
329
|
options.logProgress ??= false;
|
|
330
330
|
|
|
331
|
-
type TSubject =
|
|
331
|
+
type TSubject = {
|
|
332
332
|
tx: TEth.Tx,
|
|
333
333
|
block: TEth.Block,
|
|
334
334
|
calldata: { method, arguments: any[] }
|
|
@@ -375,7 +375,7 @@ export abstract class ContractBase {
|
|
|
375
375
|
return stream;
|
|
376
376
|
}
|
|
377
377
|
|
|
378
|
-
protected async $write
|
|
378
|
+
protected async $write(abi: string | TAbiItem, account: TAccount & { value?: number | string | bigint }, ...params): Promise<TxWriter> {
|
|
379
379
|
let writer = await this.getContractWriter();
|
|
380
380
|
return writer.writeAsync(account, abi, params, {
|
|
381
381
|
abi: this.abi,
|
|
@@ -384,20 +384,20 @@ export abstract class ContractBase {
|
|
|
384
384
|
});
|
|
385
385
|
}
|
|
386
386
|
|
|
387
|
-
protected $getAbiItem
|
|
387
|
+
protected $getAbiItem(type: 'event' | 'function' | 'string', name: string, argsCount?: number) {
|
|
388
388
|
return ContractBaseUtils.$getAbiItem(this.abi, type, name, argsCount);
|
|
389
389
|
}
|
|
390
390
|
|
|
391
|
-
protected $getAbiItemOverload
|
|
392
|
-
protected $getAbiItemOverload
|
|
393
|
-
protected $getAbiItemOverload
|
|
391
|
+
protected $getAbiItemOverload(fnName: string, args: any[])
|
|
392
|
+
protected $getAbiItemOverload(abis: (string | TAbiItem)[], args: any[])
|
|
393
|
+
protected $getAbiItemOverload(mix: string | (string | TAbiItem)[], args: any[]) {
|
|
394
394
|
let abis = typeof mix === 'string'
|
|
395
|
-
|
|
396
|
-
|
|
395
|
+
? this.abi.filter(x => x.type === 'function' && x.name === mix)
|
|
396
|
+
: mix;
|
|
397
397
|
|
|
398
398
|
let $abis = abis
|
|
399
399
|
.map(methodAbi => {
|
|
400
|
-
if (typeof methodAbi ==='string') {
|
|
400
|
+
if (typeof methodAbi === 'string') {
|
|
401
401
|
return $abiParser.parseMethod(methodAbi);
|
|
402
402
|
}
|
|
403
403
|
return methodAbi;
|
|
@@ -410,43 +410,30 @@ export abstract class ContractBase {
|
|
|
410
410
|
if ($abis.length === 1) {
|
|
411
411
|
return $abis[0];
|
|
412
412
|
}
|
|
413
|
-
$abis = $abis
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
continue;
|
|
419
|
-
}
|
|
420
|
-
if (item.type === 'bool' && typeof arg === 'boolean') {
|
|
421
|
-
continue;
|
|
422
|
-
}
|
|
423
|
-
if (item.type === 'string' && typeof arg === 'string') {
|
|
424
|
-
continue;
|
|
425
|
-
}
|
|
426
|
-
if (/^u?int/.test(item.type) && (typeof arg === 'number' || typeof arg === 'bigint')) {
|
|
427
|
-
continue;
|
|
428
|
-
}
|
|
429
|
-
if (/tuple/.test(item.type) && (typeof arg === 'object')) {
|
|
430
|
-
continue;
|
|
431
|
-
}
|
|
432
|
-
return false;
|
|
433
|
-
}
|
|
434
|
-
return true;
|
|
435
|
-
});
|
|
413
|
+
$abis = filterABIbyArguments($abis, args, 'shallow');
|
|
414
|
+
if ($abis.length === 1) {
|
|
415
|
+
return $abis[0];
|
|
416
|
+
}
|
|
417
|
+
$abis = filterABIbyArguments($abis, args, 'single');
|
|
436
418
|
if ($abis.length === 1) {
|
|
437
419
|
return $abis[0];
|
|
438
420
|
}
|
|
421
|
+
$abis = filterABIbyArguments($abis, args, 'both');
|
|
422
|
+
if ($abis.length === 1) {
|
|
423
|
+
return $abis[0];
|
|
424
|
+
}
|
|
425
|
+
|
|
439
426
|
throw new Error(`ABI not found. Got multiple overloads for the argument count ${args.length}. We should pick the ABI by parameters type.`)
|
|
440
427
|
}
|
|
441
428
|
|
|
442
|
-
protected $extractLogs
|
|
429
|
+
protected $extractLogs(tx: TEth.TxReceipt, abiItem: TAbiItem) {
|
|
443
430
|
let logs = $contract.extractLogsForAbi(tx, abiItem);
|
|
444
431
|
return logs;
|
|
445
432
|
}
|
|
446
|
-
protected $extractLog
|
|
433
|
+
protected $extractLog(log: TEth.Log, mix: string | string[] | TAbiItem | TAbiItem[] | '*') {
|
|
447
434
|
let abi: TAbiItem | TAbiItem[];
|
|
448
435
|
|
|
449
|
-
let mixArr = typeof mix === 'string' ? [
|
|
436
|
+
let mixArr = typeof mix === 'string' ? [mix] : ((mix as TAbiItem[] | string[]) ?? []);
|
|
450
437
|
if (mixArr.length === 0 || (mixArr.length === 1 && mixArr[0] === '*')) {
|
|
451
438
|
abi = this.abi;
|
|
452
439
|
} else {
|
|
@@ -459,18 +446,18 @@ export abstract class ContractBase {
|
|
|
459
446
|
protected async $getPastLogs(filters: RpcTypes.Filter, options?: {
|
|
460
447
|
streamed?: boolean
|
|
461
448
|
blockRangeLimits?: WClient['blockRangeLimits']
|
|
462
|
-
onProgress?
|
|
449
|
+
onProgress?(info: TLogsRangeProgress<TEth.Log>)
|
|
463
450
|
}) {
|
|
464
451
|
return this.getContractReader().getLogs(filters, options);
|
|
465
452
|
}
|
|
466
|
-
public async $getPastLogsParsed
|
|
453
|
+
public async $getPastLogsParsed(mix: string | TAbiItem | string[] | TAbiItem[], options?: {
|
|
467
454
|
addresses?: TAddress[]
|
|
468
455
|
fromBlock?: number | Date
|
|
469
456
|
toBlock?: number | Date
|
|
470
457
|
params?: {
|
|
471
458
|
[key: string]: any
|
|
472
459
|
}
|
|
473
|
-
onProgress?
|
|
460
|
+
onProgress?(info: TLogsRangeProgress<ITxLogItem>)
|
|
474
461
|
|
|
475
462
|
/** if TRUE the data will be only forwarded via onProgress callback.
|
|
476
463
|
* And the final array will be undefined.
|
|
@@ -516,7 +503,7 @@ export abstract class ContractBase {
|
|
|
516
503
|
abi = this.$getAbiItem('event', mix);
|
|
517
504
|
} else if (Array.isArray(mix) === false) {
|
|
518
505
|
abi = mix;
|
|
519
|
-
} else if (mix.length === 1 && typeof mix[0] ==='string' && mix[0] === '*') {
|
|
506
|
+
} else if (mix.length === 1 && typeof mix[0] === 'string' && mix[0] === '*') {
|
|
520
507
|
abi = '*';
|
|
521
508
|
} else {
|
|
522
509
|
abi = mix.map(x => {
|
|
@@ -535,7 +522,7 @@ export abstract class ContractBase {
|
|
|
535
522
|
);
|
|
536
523
|
}
|
|
537
524
|
|
|
538
|
-
private getContractReader
|
|
525
|
+
private getContractReader() {
|
|
539
526
|
let reader = this.getContractReaderInner();
|
|
540
527
|
if (this.blockDate != null) {
|
|
541
528
|
reader.forBlockAt(this.blockDate);
|
|
@@ -551,13 +538,13 @@ export abstract class ContractBase {
|
|
|
551
538
|
}
|
|
552
539
|
|
|
553
540
|
@memd.deco.memoize({ perInstance: true })
|
|
554
|
-
private getContractReaderInner
|
|
541
|
+
private getContractReaderInner() {
|
|
555
542
|
let reader = new ContractReader(this.client, { name: this.constructor.name });
|
|
556
543
|
return reader;
|
|
557
544
|
}
|
|
558
545
|
|
|
559
546
|
@memd.deco.memoize({ perInstance: true })
|
|
560
|
-
protected getContractWriter
|
|
547
|
+
protected getContractWriter() {
|
|
561
548
|
if (this.abi != null) {
|
|
562
549
|
// Updates the singleton instance
|
|
563
550
|
let logParser = di.resolve(TxTopicInMemoryProvider);
|
|
@@ -568,7 +555,7 @@ export abstract class ContractBase {
|
|
|
568
555
|
}
|
|
569
556
|
|
|
570
557
|
@memd.deco.memoize({ perInstance: true })
|
|
571
|
-
private getContractStream
|
|
558
|
+
private getContractStream() {
|
|
572
559
|
let stream = new ContractStream(this.address, this.abi, this.client);
|
|
573
560
|
return stream;
|
|
574
561
|
}
|
|
@@ -587,9 +574,9 @@ namespace BlockWalker {
|
|
|
587
574
|
}
|
|
588
575
|
}
|
|
589
576
|
|
|
590
|
-
const indexers = {} as { [key: string]: BlocksTxIndexer }
|
|
577
|
+
const indexers = {} as { [key: string]: BlocksTxIndexer };
|
|
591
578
|
|
|
592
|
-
export function onBlock
|
|
579
|
+
export function onBlock(client: Web3Client, options: IBlockWalkerOptions, cb: TBlockListener) {
|
|
593
580
|
|
|
594
581
|
let key = `${client.platform}_${options?.name ?? ''}_${options?.persistence ?? false}`;
|
|
595
582
|
let current = indexers[key];
|
|
@@ -621,7 +608,7 @@ export type TContractTypes = {
|
|
|
621
608
|
type TEventsBase = {
|
|
622
609
|
[name: string]: {
|
|
623
610
|
outputParams: Record<string, any>,
|
|
624
|
-
outputArgs:
|
|
611
|
+
outputArgs: any[],
|
|
625
612
|
}
|
|
626
613
|
}
|
|
627
614
|
|
|
@@ -631,8 +618,71 @@ export type TEventLogOptions<TParams> = {
|
|
|
631
618
|
toBlock?: number | Date
|
|
632
619
|
params?: TParams
|
|
633
620
|
streamed?: boolean
|
|
634
|
-
onProgress?
|
|
621
|
+
onProgress?(info: TLogsRangeProgress<ITxLogItem>)
|
|
635
622
|
blockRangeLimits?: WClient['blockRangeLimits']
|
|
636
623
|
}
|
|
637
624
|
|
|
638
625
|
type TEventParams<TEvents extends TEventsBase, TEventName extends keyof TEvents> = Partial<TEvents[TEventName]['outputParams']>;
|
|
626
|
+
|
|
627
|
+
|
|
628
|
+
// Tuple check type detects how an argument satisfies the "tuple"
|
|
629
|
+
// shallow: checks only that the argument is an object type
|
|
630
|
+
// single: checks that all tuple components (keys) are present in the argument
|
|
631
|
+
// both: checks that all tuple components are present in the argument AND all argument keys exist in the tuple components
|
|
632
|
+
function filterABIbyArguments(abis: TAbiItem[], args: any[], tupleCheck: 'shallow' | 'single' | 'both') {
|
|
633
|
+
return abis.filter(abi => {
|
|
634
|
+
for (let i = 0; i < args.length; i++) {
|
|
635
|
+
let item = abi.inputs[i];
|
|
636
|
+
let arg = args[i];
|
|
637
|
+
if (item.type === 'address' && $address.isValid(arg)) {
|
|
638
|
+
continue;
|
|
639
|
+
}
|
|
640
|
+
if (item.type === 'bool' && typeof arg === 'boolean') {
|
|
641
|
+
continue;
|
|
642
|
+
}
|
|
643
|
+
if (item.type === 'string' && typeof arg === 'string') {
|
|
644
|
+
continue;
|
|
645
|
+
}
|
|
646
|
+
if (/^u?int/.test(item.type) && (typeof arg === 'number' || typeof arg === 'bigint')) {
|
|
647
|
+
continue;
|
|
648
|
+
}
|
|
649
|
+
if (/tuple/.test(item.type)) {
|
|
650
|
+
arg ??= {};
|
|
651
|
+
if (tupleCheck === 'shallow') {
|
|
652
|
+
if (typeof arg === 'object') {
|
|
653
|
+
continue;
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
if (tupleCheck === 'single' || tupleCheck === 'both') {
|
|
657
|
+
// E.g. Solidity structs:
|
|
658
|
+
// 1. struct FooV1 { uint256 a; uint256 b; }
|
|
659
|
+
// 2. struct FooV2 { uint256 a; uint256 b; uint256 c; }
|
|
660
|
+
// If we call the 2. overloaded function the single check will match both structs
|
|
661
|
+
// therefore we need later to call with tupleCheck === 'both' to detect correct overload
|
|
662
|
+
const components = item.components ?? [];
|
|
663
|
+
const satisfies = components.every(x => x.name in arg) ?? false;
|
|
664
|
+
if (!satisfies) {
|
|
665
|
+
return false;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
if (tupleCheck === 'single') {
|
|
669
|
+
continue;
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
if (tupleCheck === 'both') {
|
|
673
|
+
const components = item.components ?? [];
|
|
674
|
+
for (let key in arg) {
|
|
675
|
+
const found = components.find(x => x.name === key);
|
|
676
|
+
if (!found) {
|
|
677
|
+
return false;
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
continue;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
}
|
|
684
|
+
return false;
|
|
685
|
+
}
|
|
686
|
+
return true;
|
|
687
|
+
});
|
|
688
|
+
}
|
package/src/rpc/RpcBase.ts
CHANGED
|
@@ -85,6 +85,7 @@ export abstract class RpcBase {
|
|
|
85
85
|
let body = this._wrapBody(req);
|
|
86
86
|
let subscription = await this._transport.subscribe<TReturn>(body);
|
|
87
87
|
|
|
88
|
+
|
|
88
89
|
let mapped = RpcSubscription.createMapping(subscription, this._transport, x => this._deserialize(`${req.method}.${req.params[0]}`, x))
|
|
89
90
|
return mapped as RpcSubscription<TReturn>;
|
|
90
91
|
//return subscription.map(x => this._deserialize(`${req.method}.${req.params[0]}`, x));
|
package/src/safe/SafeTx.ts
CHANGED
|
@@ -54,9 +54,16 @@ export class SafeTx {
|
|
|
54
54
|
});
|
|
55
55
|
|
|
56
56
|
let transactionsHex = $hex.concat(transactionsHexArr);
|
|
57
|
+
let isCallOnly = txData.every(tx => !tx.operation /** 0: call, 1: delegatecall */);
|
|
58
|
+
let getAddress = (key: 'MultiSend' | 'MultiSendCallOnly') => {
|
|
59
|
+
return this.options?.contracts?.[this.client.network]?.[key]
|
|
60
|
+
?? config.safe?.contracts?.[this.client.network]?.[key];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const multiSendAddress = isCallOnly
|
|
64
|
+
? (getAddress('MultiSendCallOnly') ?? getAddress('MultiSend'))
|
|
65
|
+
: (getAddress('MultiSend'))
|
|
57
66
|
|
|
58
|
-
const multiSendAddress = this.options?.contracts?.[this.client.network]?.MultiSend
|
|
59
|
-
?? config.safe?.contracts?.[this.client.network]?.MultiSend;
|
|
60
67
|
|
|
61
68
|
$require.Address(multiSendAddress, `MultiSend contract for ${this.client.network}`);
|
|
62
69
|
const safeMultiSendContract = new MultiSend(multiSendAddress, this.client);
|
package/src/utils/$traces.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { $bigint } from './$bigint';
|
|
|
6
6
|
import { $hex } from '@dequanto/utils/$hex';
|
|
7
7
|
import { $color, ColorData } from './$color';
|
|
8
8
|
import alot from 'alot';
|
|
9
|
+
import { $contract } from './$contract';
|
|
9
10
|
|
|
10
11
|
export namespace $traces {
|
|
11
12
|
|
|
@@ -335,10 +336,11 @@ export namespace $traces {
|
|
|
335
336
|
}
|
|
336
337
|
|
|
337
338
|
function formatFrameLabel(frame: TTraceFrame, contractName: string | null, abi: TEth.Abi.Item | null, params: {
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
339
|
+
shortAddress?: boolean
|
|
340
|
+
color?: boolean
|
|
341
|
+
addresses?: Record<string, string>
|
|
342
|
+
}
|
|
343
|
+
): string {
|
|
342
344
|
let head = color('gray', frame.callOp.toLowerCase(), params);
|
|
343
345
|
let suffix = '';
|
|
344
346
|
|
|
@@ -513,6 +515,13 @@ export namespace $traces {
|
|
|
513
515
|
// Fall back to raw bytes if decoding fails.
|
|
514
516
|
}
|
|
515
517
|
}
|
|
518
|
+
if (frame.failed) {
|
|
519
|
+
let abis = $contract.store.getFlattened();
|
|
520
|
+
let error = $contract.decodeCustomError(frame.output, abis);
|
|
521
|
+
if (error) {
|
|
522
|
+
return JSON.stringify(error);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
516
525
|
return shortHex(frame.output, 18, 10);
|
|
517
526
|
}
|
|
518
527
|
|