0xweb
Version:
Contract package manager and other web3 tools
94 lines (78 loc) • 3.46 kB
text/typescript
import { Web3Client } from '@dequanto/clients/Web3Client';
import { EoAccount, SafeAccount } from '@dequanto/models/TAccount';
import { TEth } from '@dequanto/models/TEth';
import { GnosisSafeHandler } from './GnosisSafeHandler';
import { $require } from '@dequanto/utils/$require';
import { TxWriter } from '@dequanto/txs/TxWriter';
import { $abiUtils } from '@dequanto/utils/$abiUtils';
import { TxDataBuilder } from '@dequanto/txs/TxDataBuilder';
import { config } from '@dequanto/config/Config';
import { MultiSend } from '@dequanto/prebuilt/safe/MultiSend';
import { ISafeServiceTransport } from './transport/ISafeServiceTransport';
import { $hex } from '@dequanto/utils/$hex';
export class SafeTx {
constructor(
public safeAccount: SafeAccount,
public client: Web3Client,
public options?: {
safeTransport?: ISafeServiceTransport
contracts?: typeof config.safe.contracts
}
) {
}
async execute (data: TEth.TxLike) {
let sender = this.safeAccount.operator ?? this.safeAccount.owners?.[0];
$require.notNull(sender, `Operator/Owner account is not set for ${ this.safeAccount.name ?? this.safeAccount.address }`);
return this.send(sender, data, {
operation: 0,
});
}
async executeBatch (...batch: Pick<TEth.TxLike, 'to' | 'data' | 'value'>[]) {
let sender = this.safeAccount.operator ?? this.safeAccount.owners?.[0];
$require.notNull(sender, `Operator/Owner account is not set for ${ this.safeAccount.name ?? this.safeAccount.address }`);
let txData = batch.map(tx => ({
operation: 0,
to: tx.to,
value: tx.value,
data: tx.data
}));
let transactionsHexArr = txData.map(tx => {
return $abiUtils.encodePacked(
[`uint8`, tx.operation ],
[`address`, tx.to],
[`uint256`, tx.value],
[`uint256`, $hex.getBytesLength(tx.data ?? '0x')],
[`bytes`, tx.data]
);
});
let transactionsHex = $hex.concat(transactionsHexArr);
const multiSendAddress = this.options?.contracts?.[this.client.network]?.MultiSend
?? config.safe?.contracts?.[this.client.network]?.MultiSend;
$require.Address(multiSendAddress, `MultiSend contract for ${this.client.network}`);
const safeMultiSendContract = new MultiSend(multiSendAddress, this.client);
const data = await safeMultiSendContract.$data().multiSend(sender, transactionsHex)
return this.send(sender, data, {
operation: 1
});
}
private async send (sender: string | EoAccount, data: TEth.TxLike, safeTxParams?: {
// 0=Call, 1=DelegateCall
operation?: 0 | 1
}) {
let safeTransport = this.options?.safeTransport ?? TxWriter.DEFAULTS.safeTransport;
let builder = new TxDataBuilder(this.client, this.safeAccount, data);
let writer = TxWriter.create(this.client, builder, sender, {
safeTransport: safeTransport
});
let handler = await GnosisSafeHandler.getInstance(
sender,
this.safeAccount,
this.client,
{
transport: safeTransport,
contracts: this.options?.contracts,
}
);
return await handler.execute(writer, safeTxParams)
}
}