dequanto 0.2.53 → 0.2.56
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/abi/$abi.js +39 -1
- package/lib/cjs/abi/$abi.js.map +1 -1
- package/lib/cjs/contracts/ContractReader.js +2 -2
- package/lib/cjs/contracts/ContractReader.js.map +1 -1
- package/lib/cjs/gen/Generator.js +1 -0
- package/lib/cjs/gen/Generator.js.map +1 -1
- package/lib/cjs/gen/GeneratorFromAbi.js +38 -9
- package/lib/cjs/gen/GeneratorFromAbi.js.map +1 -1
- package/lib/cjs/safe/GnosisSafeHandler.js.map +1 -1
- package/lib/cjs/services/TimelockService/ITimelockService.js.map +1 -1
- package/lib/cjs/services/TimelockService/TimelockService.js +1 -1
- package/lib/cjs/services/TimelockService/TimelockService.js.map +1 -1
- package/lib/cjs/solidity/utils/$types.js +26 -0
- package/lib/cjs/solidity/utils/$types.js.map +1 -1
- package/lib/cjs/txs/TxWriter.js +6 -4
- package/lib/cjs/txs/TxWriter.js.map +1 -1
- package/lib/cjs/txs/agents/BatchAgent.js +32 -7
- package/lib/cjs/txs/agents/BatchAgent.js.map +1 -1
- package/lib/cjs/txs/agents/TxWriterAccountAgents.js +2 -0
- package/lib/cjs/txs/agents/TxWriterAccountAgents.js.map +1 -1
- package/lib/cjs/txs/agents/ZodiacAgent.js +20 -0
- package/lib/cjs/txs/agents/ZodiacAgent.js.map +1 -0
- package/lib/cjs/utils/$account.js +5 -1
- package/lib/cjs/utils/$account.js.map +1 -1
- package/lib/cjs/zodiac/ZodiacTx.js +83 -0
- package/lib/cjs/zodiac/ZodiacTx.js.map +1 -0
- package/lib/esm/abi/$abi.js.map +1 -1
- package/lib/esm/abi/$abi.mjs +36 -1
- package/lib/esm/contracts/ContractReader.js.map +1 -1
- package/lib/esm/contracts/ContractReader.mjs +2 -2
- package/lib/esm/gen/Generator.js.map +1 -1
- package/lib/esm/gen/Generator.mjs +1 -0
- package/lib/esm/gen/GeneratorFromAbi.js.map +1 -1
- package/lib/esm/gen/GeneratorFromAbi.mjs +38 -9
- package/lib/esm/safe/GnosisSafeHandler.js.map +1 -1
- package/lib/esm/services/TimelockService/ITimelockService.js.map +1 -1
- package/lib/esm/services/TimelockService/TimelockService.js.map +1 -1
- package/lib/esm/services/TimelockService/TimelockService.mjs +1 -1
- package/lib/esm/solidity/utils/$types.js.map +1 -1
- package/lib/esm/solidity/utils/$types.mjs +26 -0
- package/lib/esm/txs/TxWriter.js.map +1 -1
- package/lib/esm/txs/TxWriter.mjs +6 -4
- package/lib/esm/txs/agents/BatchAgent.js.map +1 -1
- package/lib/esm/txs/agents/BatchAgent.mjs +32 -7
- package/lib/esm/txs/agents/TxWriterAccountAgents.js.map +1 -1
- package/lib/esm/txs/agents/TxWriterAccountAgents.mjs +2 -0
- package/lib/esm/txs/agents/ZodiacAgent.js.map +1 -0
- package/lib/esm/txs/agents/ZodiacAgent.mjs +16 -0
- package/lib/esm/utils/$account.js.map +1 -1
- package/lib/esm/utils/$account.mjs +5 -1
- package/lib/esm/zodiac/ZodiacTx.js.map +1 -0
- package/lib/esm/zodiac/ZodiacTx.mjs +79 -0
- package/lib/types/contracts/ContractReader.d.ts +1 -1
- package/lib/types/gen/Generator.d.ts +17 -0
- package/lib/types/gen/GeneratorFromAbi.d.ts +7 -0
- package/lib/types/models/TAccount.d.ts +11 -2
- package/lib/types/models/TEth.d.ts +4 -1
- package/lib/types/services/TimelockService/ITimelockService.d.ts +1 -0
- package/lib/types/solidity/utils/$types.d.ts +8 -0
- package/lib/types/txs/agents/BatchAgent.d.ts +2 -1
- package/lib/types/txs/agents/ZodiacAgent.d.ts +7 -0
- package/lib/types/utils/$account.d.ts +2 -1
- package/lib/types/zodiac/ZodiacTx.d.ts +30 -0
- package/package.json +1 -1
- package/skills/dequanto/INDEX.md +1 -1
- package/skills/dequanto/SKILL.md +4 -3
- package/skills/dequanto/examples/browser-wallet.spec.ts +2 -1
- package/skills/dequanto/examples/config.spec.ts +2 -1
- package/skills/dequanto/examples/contract-read.spec.ts +2 -1
- package/skills/dequanto/examples/contract-write.spec.ts +2 -1
- package/skills/dequanto/examples/deploy-contract.spec.ts +2 -1
- package/skills/dequanto/examples/erc4337-userop.spec.ts +2 -1
- package/skills/dequanto/examples/explorer-abi.spec.ts +2 -1
- package/skills/dequanto/examples/generate-contract-class.spec.ts +2 -1
- package/skills/dequanto/examples/hardhat-debug.spec.ts +2 -1
- package/skills/dequanto/examples/hardhat-fork.spec.ts +2 -1
- package/skills/dequanto/examples/index-events.spec.ts +2 -1
- package/skills/dequanto/examples/live-events.spec.ts +2 -1
- package/skills/dequanto/examples/revert-error.spec.ts +2 -1
- package/skills/dequanto/examples/rpc-read.spec.ts +19 -5
- package/skills/dequanto/examples/safe-batch.spec.ts +92 -3
- package/skills/dequanto/examples/send-transaction.spec.ts +2 -1
- package/skills/dequanto/examples/storage.spec.ts +2 -1
- package/skills/dequanto/examples/token-transfer.spec.ts +2 -1
- package/skills/dequanto/examples/utils.spec.ts +2 -1
- package/skills/dequanto/references/safe-erc4337.md +50 -3
- package/skills/dequanto/references/tokens-accounts.md +1 -0
- package/skills/dequanto/references/transactions.md +2 -1
- package/src/abi/$abi.ts +36 -0
- package/src/contracts/ContractReader.ts +2 -2
- package/src/gen/Generator.ts +4 -0
- package/src/gen/GeneratorFromAbi.ts +40 -10
- package/src/models/TAccount.ts +17 -2
- package/src/models/TEth.ts +4 -1
- package/src/safe/GnosisSafeHandler.ts +12 -12
- package/src/services/TimelockService/ITimelockService.ts +2 -0
- package/src/services/TimelockService/TimelockService.ts +1 -1
- package/src/solidity/utils/$types.ts +27 -0
- package/src/txs/TxWriter.ts +6 -4
- package/src/txs/agents/BatchAgent.ts +33 -7
- package/src/txs/agents/TxWriterAccountAgents.ts +2 -0
- package/src/txs/agents/ZodiacAgent.ts +19 -0
- package/src/utils/$account.ts +6 -2
- package/src/zodiac/ZodiacTx.ts +99 -0
- package/typings/index.d.ts +1 -4
- package/typings/globals/atma-utest/index.d.ts +0 -53
- package/typings/globals/atma-utest/typings.json +0 -10
- package/typings/globals/axios/index.d.ts +0 -6
- package/typings/globals/mask/index.d.ts +0 -6
- package/typings/globals/mask/typings.json +0 -9
|
@@ -45,10 +45,10 @@ export class GnosisSafeHandler {
|
|
|
45
45
|
this.client = config.client ?? di.resolve(EthWeb3Client);
|
|
46
46
|
this.transport = config.transport ?? (
|
|
47
47
|
config.owners.length > 1
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
// when multiple owners are provided assume the transport is InMemory
|
|
49
|
+
? new InMemoryServiceTransport(this.client, this.owners[0])
|
|
50
|
+
// otherwise use the default Safe Transaction Service
|
|
51
|
+
: new SafeServiceTransport(this.client, this.owners)
|
|
52
52
|
)
|
|
53
53
|
|
|
54
54
|
$require.Address(this.safeAddress, `Safe address ${this.safeAddress} is not valid`);
|
|
@@ -147,7 +147,7 @@ export class GnosisSafeHandler {
|
|
|
147
147
|
return tx;
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
-
async executeTxData
|
|
150
|
+
async executeTxData(txData: TEth.TxLike, owner: EoAccount, safeTxParams?: {
|
|
151
151
|
// 0 - Call (default)
|
|
152
152
|
// 1 - DelegateCall
|
|
153
153
|
operation?: 0 | 1
|
|
@@ -158,7 +158,7 @@ export class GnosisSafeHandler {
|
|
|
158
158
|
return tx;
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
-
async createTxHash
|
|
161
|
+
async createTxHash(builder: TxDataBuilder, value?: bigint, safeTxParams?: {
|
|
162
162
|
operation?: 0 | 1
|
|
163
163
|
}) {
|
|
164
164
|
let txData = builder.getTxData(this.client);
|
|
@@ -234,7 +234,7 @@ export class GnosisSafeHandler {
|
|
|
234
234
|
let txProps: SafeServiceTypes.ProposeTransactionProps = {
|
|
235
235
|
safeAddress: $address.toChecksum(this.safeAddress),
|
|
236
236
|
senderAddress: $address.toChecksum(owner.address),
|
|
237
|
-
safeTransaction: <SafeServiceTypes.SafeTransaction>
|
|
237
|
+
safeTransaction: <SafeServiceTypes.SafeTransaction>{
|
|
238
238
|
data: safeTxData,
|
|
239
239
|
signatures: signatures,
|
|
240
240
|
},
|
|
@@ -286,11 +286,11 @@ export class GnosisSafeHandler {
|
|
|
286
286
|
})
|
|
287
287
|
}
|
|
288
288
|
|
|
289
|
-
static parseSafeTx(buffer: TEth.Hex, value?): { name, args: any[]} {
|
|
290
|
-
return $abiUtils.parseMethodCallData([
|
|
289
|
+
static parseSafeTx(buffer: TEth.Hex, value?): { name, args: any[] } {
|
|
290
|
+
return $abiUtils.parseMethodCallData([SafeAbi.execTransaction], { input: buffer, value });
|
|
291
291
|
}
|
|
292
292
|
|
|
293
|
-
static async getInstance
|
|
293
|
+
static async getInstance(senderMix: string | EoAccount, safeAccount: SafeAccount, client: Web3Client, options: {
|
|
294
294
|
transport?: ISafeServiceTransport
|
|
295
295
|
contracts?: typeof config.safe.contracts
|
|
296
296
|
}): Promise<GnosisSafeHandler> {
|
|
@@ -298,7 +298,7 @@ export class GnosisSafeHandler {
|
|
|
298
298
|
? await ChainAccountService.get(senderMix) as EoAccount
|
|
299
299
|
: senderMix;
|
|
300
300
|
|
|
301
|
-
let owners = [
|
|
301
|
+
let owners = [sender];
|
|
302
302
|
|
|
303
303
|
if (safeAccount.owners) {
|
|
304
304
|
let others = await alot(safeAccount.owners)
|
|
@@ -408,7 +408,7 @@ const SafeAbi = {
|
|
|
408
408
|
}
|
|
409
409
|
]
|
|
410
410
|
},
|
|
411
|
-
getTransactionHash: <TAbiItem>
|
|
411
|
+
getTransactionHash: <TAbiItem>{
|
|
412
412
|
"type": "function",
|
|
413
413
|
"stateMutability": "view",
|
|
414
414
|
"outputs": [
|
|
@@ -86,10 +86,10 @@ export class TimelockService implements ITimelockService {
|
|
|
86
86
|
let [ callSalt ] = callSaltArr;
|
|
87
87
|
|
|
88
88
|
let [ callScheduleFirst ] = callScheduled;
|
|
89
|
-
callScheduleFirst.params.delay
|
|
90
89
|
|
|
91
90
|
let schedule = {
|
|
92
91
|
sender: null,
|
|
92
|
+
timelock: callScheduleFirst.address,
|
|
93
93
|
key: callSalt.params.id,
|
|
94
94
|
id: callSalt.params.id,
|
|
95
95
|
salt: callSalt.params.salt,
|
|
@@ -2,6 +2,7 @@ import { $abiParser } from 'dequanto/utils/$abiParser';
|
|
|
2
2
|
import { $abiType } from 'dequanto/utils/$abiType';
|
|
3
3
|
import { $abiUtils } from 'dequanto/utils/$abiUtils';
|
|
4
4
|
import alot from 'alot';
|
|
5
|
+
import { type TAbiInput } from 'dequanto/types/TAbi';
|
|
5
6
|
|
|
6
7
|
export namespace $types {
|
|
7
8
|
export function isFixedArray (type: string) {
|
|
@@ -23,6 +24,11 @@ export namespace $types {
|
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Returns the type size in bits, excluding ABI padding.
|
|
29
|
+
* Sums element sizes for fixed arrays and tuple declarations.
|
|
30
|
+
* Returns Infinity for dynamic or unknown types.
|
|
31
|
+
*/
|
|
26
32
|
export function sizeOf(type: string) {
|
|
27
33
|
if (type === 'address') {
|
|
28
34
|
// 20bytes
|
|
@@ -58,4 +64,25 @@ export namespace $types {
|
|
|
58
64
|
}
|
|
59
65
|
return Infinity;
|
|
60
66
|
}
|
|
67
|
+
|
|
68
|
+
/** Number of 32-byte ABI words; Infinity for dynamic or unknown types. */
|
|
69
|
+
export function wordSizeOf(type: string | TAbiInput): number {
|
|
70
|
+
let input = typeof type === 'string' ? { type } : type;
|
|
71
|
+
let name = input.type.trim();
|
|
72
|
+
if (isFixedArray(name)) {
|
|
73
|
+
let baseType = $abiType.array.getBaseType(name);
|
|
74
|
+
let words = wordSizeOf({ ...input, type: baseType });
|
|
75
|
+
return Number.isFinite(words) ? words * $abiType.array.getLength(name) : Infinity;
|
|
76
|
+
}
|
|
77
|
+
if (isDynamicArray(name)) {
|
|
78
|
+
return Infinity;
|
|
79
|
+
}
|
|
80
|
+
if (name === 'tuple') {
|
|
81
|
+
return input.components == null ? Infinity : alot(input.components).sum(x => wordSizeOf(x));
|
|
82
|
+
}
|
|
83
|
+
if (isStruct(name) || name === '()') {
|
|
84
|
+
return alot($abiParser.parseArguments(name)).sum(x => wordSizeOf(x));
|
|
85
|
+
}
|
|
86
|
+
return Math.ceil(sizeOf(name) / 256);
|
|
87
|
+
}
|
|
61
88
|
}
|
package/src/txs/TxWriter.ts
CHANGED
|
@@ -673,10 +673,12 @@ export class TxWriter extends class_EventEmitter<ITxWriterEvents> implements ITx
|
|
|
673
673
|
let account = await TxWriter.prepareAccount(accountMix);
|
|
674
674
|
let txBuilder = new TxDataBuilder(client, account, data);
|
|
675
675
|
|
|
676
|
-
await
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
676
|
+
if (await TxWriter.hasAgent(account) === false) {
|
|
677
|
+
await Promise.all([
|
|
678
|
+
txBuilder.ensureGas(),
|
|
679
|
+
txBuilder.ensureNonce(),
|
|
680
|
+
]);
|
|
681
|
+
}
|
|
680
682
|
|
|
681
683
|
let w = new TxWriter(client, txBuilder, account);
|
|
682
684
|
w.send(options);
|
|
@@ -12,6 +12,7 @@ import { $date } from 'dequanto/utils/$date';
|
|
|
12
12
|
import { $address } from 'dequanto/utils/$address';
|
|
13
13
|
import { $logger } from 'dequanto/utils/$logger';
|
|
14
14
|
import { SafeTx } from 'dequanto/safe/SafeTx';
|
|
15
|
+
import { ZodiacTx } from 'dequanto/zodiac/ZodiacTx';
|
|
15
16
|
import { TimelockController } from 'dequanto/prebuilt/openzeppelin/TimelockController';
|
|
16
17
|
import { TimelockService } from 'dequanto/services/TimelockService/TimelockService';
|
|
17
18
|
import { TxDataBuilder } from '../TxDataBuilder';
|
|
@@ -86,7 +87,7 @@ export class BatchAgent implements ITxWriterAgent {
|
|
|
86
87
|
/**
|
|
87
88
|
* Executes the queued transactions.
|
|
88
89
|
*
|
|
89
|
-
* By default, duplicate transactions are skipped. If the account is Safe or Timelock,
|
|
90
|
+
* By default, duplicate transactions are skipped. If the account is Safe, Zodiac, or Timelock,
|
|
90
91
|
* prepares the corresponding calldata and submits it as a batch transaction.
|
|
91
92
|
*
|
|
92
93
|
* @param options.includeDuplicates Include duplicate transactions in the execution batch.
|
|
@@ -100,10 +101,10 @@ export class BatchAgent implements ITxWriterAgent {
|
|
|
100
101
|
if (options?.includeDuplicates !== true) {
|
|
101
102
|
txs = alot(txs).distinctBy(x => {
|
|
102
103
|
const data = x.outerWriter.builder.data;
|
|
103
|
-
|
|
104
|
-
// remove duplicates by [from,to,data]
|
|
104
|
+
// Remove duplicates by account, value, target, and calldata.
|
|
105
105
|
return [
|
|
106
|
-
|
|
106
|
+
this.getAccountKey(x),
|
|
107
|
+
String(data.value ?? 0),
|
|
107
108
|
data.to?.toLowerCase() ?? '',
|
|
108
109
|
data.data ?? ''
|
|
109
110
|
].join('');
|
|
@@ -117,10 +118,10 @@ export class BatchAgent implements ITxWriterAgent {
|
|
|
117
118
|
? txs[i + 1]
|
|
118
119
|
: null;
|
|
119
120
|
|
|
120
|
-
let acc0 =
|
|
121
|
-
let acc1 = next
|
|
121
|
+
let acc0 = this.getAccountKey(tx);
|
|
122
|
+
let acc1 = next == null ? null : this.getAccountKey(next);
|
|
122
123
|
|
|
123
|
-
if (next == null ||
|
|
124
|
+
if (next == null || acc0 !== acc1) {
|
|
124
125
|
let arr = await this.executeGroup(txs.slice(groupStart, i + 1));
|
|
125
126
|
writers.push(...arr);
|
|
126
127
|
groupStart = i + 1;
|
|
@@ -175,9 +176,34 @@ export class BatchAgent implements ITxWriterAgent {
|
|
|
175
176
|
return lines.join('\n');
|
|
176
177
|
}
|
|
177
178
|
|
|
179
|
+
private getAccountKey (tx: MockTxWriter): string {
|
|
180
|
+
let account = tx.account ?? tx.sender;
|
|
181
|
+
let address = (account.address ?? tx.sender?.address)?.toLowerCase();
|
|
182
|
+
if ($account.isZodiac(account)) {
|
|
183
|
+
let roleKey = account.roleKey?.toLowerCase() ?? '';
|
|
184
|
+
return `${address}-${roleKey}`;
|
|
185
|
+
}
|
|
186
|
+
return address;
|
|
187
|
+
}
|
|
188
|
+
|
|
178
189
|
private async executeGroup (txs: MockTxWriter[]) {
|
|
179
190
|
let { account, sender } = txs[0];
|
|
180
191
|
let acc = account ?? sender;
|
|
192
|
+
if ($account.isZodiac(acc)) {
|
|
193
|
+
let first = txs[0].outerWriter;
|
|
194
|
+
let { client, builder, options } = first;
|
|
195
|
+
let zodiac = new ZodiacTx({
|
|
196
|
+
...acc,
|
|
197
|
+
operator: sender ?? acc.operator
|
|
198
|
+
}, client, {
|
|
199
|
+
builder: builder.config,
|
|
200
|
+
writer: options,
|
|
201
|
+
});
|
|
202
|
+
let calls = txs.map(x => x.outerWriter.builder.getTxData());
|
|
203
|
+
let writer = await zodiac.executeBatch(...calls);
|
|
204
|
+
await writer.wait();
|
|
205
|
+
return [writer];
|
|
206
|
+
}
|
|
181
207
|
if ($account.isSafe(acc)) {
|
|
182
208
|
let tx = await this.executeBatchSafe(acc, txs);
|
|
183
209
|
return [ tx ];
|
|
@@ -3,6 +3,7 @@ import type { ITxWriterEmitter, TxWriter } from '../TxWriter';
|
|
|
3
3
|
import { SafeAgent } from './SafeAgent';
|
|
4
4
|
import { Erc4337Agent } from './Erc4337Agent';
|
|
5
5
|
import { TimelockAgent } from './TimelockAgent';
|
|
6
|
+
import { ZodiacAgent } from './ZodiacAgent';
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
export interface ITxWriterAgent {
|
|
@@ -17,6 +18,7 @@ export namespace TxWriterAccountAgents {
|
|
|
17
18
|
|
|
18
19
|
const agents: ITxWriterAccountAgent[] = [
|
|
19
20
|
new SafeAgent(),
|
|
21
|
+
new ZodiacAgent(),
|
|
20
22
|
new Erc4337Agent(),
|
|
21
23
|
new TimelockAgent(),
|
|
22
24
|
];
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { EoAccount, TAccount, ZodiacAccount } from 'dequanto/models/TAccount';
|
|
2
|
+
import { $account } from 'dequanto/utils/$account';
|
|
3
|
+
import { ZodiacTx } from 'dequanto/zodiac/ZodiacTx';
|
|
4
|
+
import { TxWriter } from '../TxWriter';
|
|
5
|
+
import { ITxWriterAccountAgent } from './TxWriterAccountAgents';
|
|
6
|
+
|
|
7
|
+
export class ZodiacAgent implements ITxWriterAccountAgent {
|
|
8
|
+
supports (account: TAccount) {
|
|
9
|
+
return $account.isZodiac(account);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async process (sender: EoAccount, account: ZodiacAccount, outerWriter: TxWriter) {
|
|
13
|
+
let zodiac = new ZodiacTx({ ...account, operator: sender }, outerWriter.client, {
|
|
14
|
+
builder: outerWriter.builder.config,
|
|
15
|
+
writer: outerWriter.options,
|
|
16
|
+
});
|
|
17
|
+
return zodiac.execute(outerWriter.builder.getTxData());
|
|
18
|
+
}
|
|
19
|
+
}
|
package/src/utils/$account.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EoAccount, Erc4337Account, SafeAccount, TAccount, TimelockAccount } from "dequanto/models/TAccount";
|
|
1
|
+
import { EoAccount, Erc4337Account, SafeAccount, TAccount, TimelockAccount, ZodiacAccount } from "dequanto/models/TAccount";
|
|
2
2
|
import { $address } from './$address';
|
|
3
3
|
import { $require } from './$require';
|
|
4
4
|
import { $sig } from './$sig';
|
|
@@ -13,7 +13,7 @@ export namespace $account {
|
|
|
13
13
|
return { name: account };
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
let acc = isSafe(account) || isErc4337 (account) || isTimelock(account)
|
|
16
|
+
let acc = isSafe(account) || isErc4337 (account) || isTimelock(account) || isZodiac(account)
|
|
17
17
|
? account.operator
|
|
18
18
|
: account;
|
|
19
19
|
|
|
@@ -21,6 +21,10 @@ export namespace $account {
|
|
|
21
21
|
return acc as EoAccount;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
export function isZodiac (account: TAccount): account is ZodiacAccount {
|
|
25
|
+
return account != null && typeof account === 'object' && account.type === 'zodiac';
|
|
26
|
+
}
|
|
27
|
+
|
|
24
28
|
export function isSafe (account:TAccount): account is SafeAccount {
|
|
25
29
|
if (account == null) {
|
|
26
30
|
return false;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { Web3Client } from 'dequanto/clients/Web3Client';
|
|
2
|
+
import { ZodiacAccount } from 'dequanto/models/TAccount';
|
|
3
|
+
import { TEth } from 'dequanto/models/TEth';
|
|
4
|
+
import { config } from 'dequanto/config/Config';
|
|
5
|
+
import { ITxBuilderOptions } from 'dequanto/txs/ITxBuilderOptions';
|
|
6
|
+
import { TxDataBuilder } from 'dequanto/txs/TxDataBuilder';
|
|
7
|
+
import { ITxWriterOptions, TxWriter } from 'dequanto/txs/TxWriter';
|
|
8
|
+
import { $abi } from 'dequanto/abi/$abi';
|
|
9
|
+
import { $abiUtils } from 'dequanto/utils/$abiUtils';
|
|
10
|
+
import { $hex } from 'dequanto/utils/$hex';
|
|
11
|
+
import { $require } from 'dequanto/utils/$require';
|
|
12
|
+
|
|
13
|
+
type TCall = Pick<TEth.TxLike, 'to' | 'data' | 'value'>;
|
|
14
|
+
|
|
15
|
+
/** Roles v2 execution. Inner values are paid by the avatar, not the operator. */
|
|
16
|
+
export class ZodiacTx {
|
|
17
|
+
constructor (
|
|
18
|
+
public account: ZodiacAccount,
|
|
19
|
+
public client: Web3Client,
|
|
20
|
+
public options?: {
|
|
21
|
+
contracts?: typeof config.safe.contracts
|
|
22
|
+
builder?: ITxBuilderOptions
|
|
23
|
+
writer?: ITxWriterOptions
|
|
24
|
+
}
|
|
25
|
+
) {}
|
|
26
|
+
|
|
27
|
+
/** Encode a transaction to the Roles Modifier without submitting it. */
|
|
28
|
+
getTxData (call: TCall, operation: 0 | 1 = 0): TEth.TxLike {
|
|
29
|
+
$require.Address(this.account.address, 'Zodiac Roles Modifier address');
|
|
30
|
+
$require.Hex(this.account.roleKey, 'Zodiac roleKey must be hex');
|
|
31
|
+
$require.Address(call.to, 'Zodiac transaction target');
|
|
32
|
+
return {
|
|
33
|
+
to: this.account.address,
|
|
34
|
+
value: 0n,
|
|
35
|
+
data: $abi.encodeCall('execTransactionWithRole(address to,uint256 value,bytes data,uint8 operation,bytes32 roleKey,bool shouldRevert)', [
|
|
36
|
+
call.to,
|
|
37
|
+
call.value ?? 0n,
|
|
38
|
+
call.data ?? '0x',
|
|
39
|
+
operation,
|
|
40
|
+
$hex.padBytes(this.account.roleKey ?? '0x0', 32),
|
|
41
|
+
true
|
|
42
|
+
])
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** The Roles Modifier must have an unwrapper registered for this MultiSend deployment. */
|
|
47
|
+
getBatchTxData (...calls: TCall[]): TEth.TxLike {
|
|
48
|
+
$require.gt(calls.length, 0, 'Zodiac batch must not be empty');
|
|
49
|
+
let getAddress = (key: 'MultiSend' | 'MultiSendCallOnly') => {
|
|
50
|
+
return this.options?.contracts?.[this.client.network]?.[key]
|
|
51
|
+
?? config.safe?.contracts?.[this.client.network]?.[key];
|
|
52
|
+
};
|
|
53
|
+
let multiSendAddress = getAddress('MultiSendCallOnly') ?? getAddress('MultiSend');
|
|
54
|
+
$require.Address(multiSendAddress, 'Zodiac MultiSend contract');
|
|
55
|
+
let transactions = calls.map(call => {
|
|
56
|
+
$require.Address(call.to, 'Zodiac batch transaction target');
|
|
57
|
+
let data = call.data ?? '0x';
|
|
58
|
+
return $abiUtils.encodePacked(
|
|
59
|
+
['uint8', 0],
|
|
60
|
+
['address', call.to],
|
|
61
|
+
['uint256', call.value ?? 0n],
|
|
62
|
+
['uint256', $hex.getBytesLength(data)],
|
|
63
|
+
['bytes', data]
|
|
64
|
+
);
|
|
65
|
+
});
|
|
66
|
+
return this.getTxData({
|
|
67
|
+
to: multiSendAddress,
|
|
68
|
+
value: 0n,
|
|
69
|
+
data: $abi.encodeCall('multiSend(bytes transactions)', [$hex.concat(transactions)])
|
|
70
|
+
}, 1);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async execute (call: TCall) {
|
|
74
|
+
return this.send(this.getTxData(call));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async executeBatch (...calls: TCall[]) {
|
|
78
|
+
return this.send(this.getBatchTxData(...calls));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
private async send (data: TEth.TxLike) {
|
|
82
|
+
$require.notNull(this.account.operator, 'Zodiac operator is required');
|
|
83
|
+
let sender = await TxWriter.prepareAccount(this.account.operator);
|
|
84
|
+
let builder = new TxDataBuilder(this.client, sender, data, this.options?.builder);
|
|
85
|
+
let config = this.options?.builder;
|
|
86
|
+
await builder.setGas({
|
|
87
|
+
price: config?.gasPrice,
|
|
88
|
+
priceRatio: config?.gasPriceRatio,
|
|
89
|
+
gasLimit: config?.gasLimit,
|
|
90
|
+
gasLimitRatio: config?.gasLimitRatio,
|
|
91
|
+
gasEstimation: config?.gasEstimation,
|
|
92
|
+
from: config?.from ?? sender.address,
|
|
93
|
+
type: config?.type,
|
|
94
|
+
});
|
|
95
|
+
return TxWriter
|
|
96
|
+
.create(this.client, builder, sender)
|
|
97
|
+
.send(this.options?.writer);
|
|
98
|
+
}
|
|
99
|
+
}
|
package/typings/index.d.ts
CHANGED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
// Generated by typings
|
|
2
|
-
// Source: https://raw.githubusercontent.com/atmajs/utest/master/types/index.d.ts
|
|
3
|
-
declare module "atma-utest-global" {
|
|
4
|
-
export = UTest;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
declare var UTest: IUtest;
|
|
8
|
-
|
|
9
|
-
declare interface IUtest {
|
|
10
|
-
(definition: IUTestDefinition): void
|
|
11
|
-
|
|
12
|
-
domtest: IDomTest
|
|
13
|
-
request (url, method, headers, data, callback)
|
|
14
|
-
server: {
|
|
15
|
-
render (template: string, ...args)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
benchmark (model: IUTestDefinition)
|
|
19
|
-
benchmarkVersions (model: IUTestDefinition)
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
interface IDomTest {
|
|
24
|
-
(subject: HTMLElement | JQuery | any, testMarkup: string | any): PromiseLike<any>
|
|
25
|
-
use (astName: string): IDomTest
|
|
26
|
-
process (subject: HTMLElement | JQuery | any, testMarkup: string | any): PromiseLike<any>
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
interface IUTestDefinition {
|
|
30
|
-
$config?: {
|
|
31
|
-
timeout?: number
|
|
32
|
-
errorableCallbacks?: boolean
|
|
33
|
-
breakOnError?: boolean
|
|
34
|
-
|
|
35
|
-
'http.config'?: any
|
|
36
|
-
'http.eval'?: string
|
|
37
|
-
'http.include'?: any
|
|
38
|
-
'http.service'?: any
|
|
39
|
-
'http.process'?: any
|
|
40
|
-
'util.process'?: any
|
|
41
|
-
}
|
|
42
|
-
$before?: (done?: Function) => void | PromiseLike<any>
|
|
43
|
-
$after?: (done?: Function) => void | PromiseLike<any>
|
|
44
|
-
$teardown?: (done?: Function) => void | PromiseLike<any>
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
[key: string]: ITestCase | IUTestDefinition | any
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
interface ITestCase {
|
|
52
|
-
(done?: Function, ...args: any[]): void | PromiseLike<any> | any
|
|
53
|
-
}
|