Skip to content

Commit

Permalink
feat(core): add MultiSenderAction
Browse files Browse the repository at this point in the history
  • Loading branch information
extg3 committed Jun 26, 2024
1 parent 39092cf commit d7d997e
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 35 deletions.
36 changes: 12 additions & 24 deletions examples/sandbox/src/app/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import {
WorkflowsFactory,
BrowserStorage,
Address,
InstantTrigger,
MultiSenderAction,
} from '@ditto-network/core';
import { EthersSigner, EthersContractFactory } from '@ditto-network/ethers';
import useLocalStorage from '../hooks/use-local-storage';
Expand Down Expand Up @@ -181,32 +183,18 @@ export function App() {
const wf = await workflowFactory.create({
name: 'My first workflow',
triggers: [
new TimeBasedTrigger(
{
repeatTimes: 2,
startAtTimestamp: new Date().getTime() / 1000 + 60,
cycle: {
frequency: 2,
scale: TimeScale.Minutes,
},
},
commonConfig
),
new InstantTrigger(),
],
actions: [
new UniswapSwapActionCallDataBuilder(
{
fromToken: tokens.wmatic,
toToken: tokens.usdt,
fromAmount: parseUnits('100', 6).toString(),
slippagePercent: 0.05,
providerStrategy: {
type: 'browser',
provider: (window as any).ethereum!,
},
},
commonConfig
),
new MultiSenderAction({
items: [
{
to: account as Address,
amount: parseUnits('0.01', 18),
asset: tokens.usdt,
}
],
}, commonConfig)
],
chainId,
});
Expand Down
8 changes: 8 additions & 0 deletions packages/core/src/lib/contracts/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,11 @@ export interface DittoContractInterface {
export class DittoContractNotInitializedError extends Error {}

export class DittoContractMethodNotFoundError extends Error {}


export interface Erc20Token {
symbol: string
address: Address
decimals: number
name: string
}
3 changes: 2 additions & 1 deletion packages/core/src/lib/ditto-sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Token, TokenLight } from './blockchain/tokens';
import { tokens } from './blockchain/tokens';
import { Provider } from './provider';
import { BrowserStorage, InMemoryStorage } from './storage';
import { WorkflowsFactory, PriceTrigger, TimeBasedTrigger, TimeScale } from './workflow';
import { WorkflowsFactory, PriceTrigger, TimeBasedTrigger, TimeScale, InstantTrigger } from './workflow';
import { SmartWalletFactory } from './vaults';
import type { WorkflowExecution } from './workflow';
import { BaseApiError } from './network/api-client';
Expand Down Expand Up @@ -52,6 +52,7 @@ export {
TimeBasedTrigger,
DittoContractNotInitializedError,
DittoContractMethodNotFoundError,
InstantTrigger,
};

export type {
Expand Down
5 changes: 2 additions & 3 deletions packages/core/src/lib/workflow/actions/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
import { UniswapSwapActionCallDataBuilder } from './uniswap-swap/uniswap-swap-action';

export { UniswapSwapActionCallDataBuilder };
export { UniswapSwapActionCallDataBuilder } from './uniswap-swap/uniswap-swap-action';
export { MultiSenderAction } from './multisender/multisender';
77 changes: 77 additions & 0 deletions packages/core/src/lib/workflow/actions/multisender/multisender.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { ethers } from 'ethers5';
import BigNumber from 'bignumber.js';
import { AlphaRouter, AlphaRouterParams, SwapType } from '@uniswap/smart-order-router';
import { CurrencyAmount, Percent, Token as UniswapToken, TradeType } from '@uniswap/sdk-core';
import VaultABI from '../../../blockchain/abi/VaultABI.json';
import Erc20TokenABI from '../../../blockchain/abi/Erc20TokenABI.json';
import { TokenLight, tokens } from '../../../blockchain/tokens';
import { Chain } from '../../../blockchain/chains/types';
import {
CallData,
CallDataBuilder,
CallDataBuilderReturnData,
CommonBuilderOptions,
} from '../../builders/types';
import { isNativeToken, isAddressesEqual } from '../../../blockchain/tokens/utils';
import { DittoContractInterface, Erc20Token } from '../../../contracts/types';
import { Address } from '../../../types';

export type MultiSenderItem = {
asset: Erc20Token | null;
amount: bigint;
to: Address;
};

type ActionConfig = {
items: MultiSenderItem[];
};

export class MultiSenderAction implements CallDataBuilder {
constructor(
protected readonly config: ActionConfig,
protected readonly commonCallDataBuilderConfig: CommonBuilderOptions
) {}

public async build(): Promise<CallDataBuilderReturnData> {
const callData = new Set<CallData>();

const vaultInterface = this.commonCallDataBuilderConfig.provider
.getContractFactory()
.getContractInterface(JSON.stringify(VaultABI));
const erc20Interface = this.commonCallDataBuilderConfig.provider
.getContractFactory()
.getContractInterface(JSON.stringify(Erc20TokenABI));

const { chainId } = this.commonCallDataBuilderConfig;

for (const item of this.config.items) {
if (!item.to || !item.amount) continue;

const asset = item.asset || tokens.native[chainId];
const amount = item.amount // new BigNumber(item.amount).shiftedBy(asset.decimals).toFixed(0)

const isTokenNative = isNativeToken(
asset.address,
this.commonCallDataBuilderConfig.chainId
);

if (isTokenNative) {
callData.add({
to: this.commonCallDataBuilderConfig.vaultAddress,
callData: vaultInterface.encodeFunctionData('withdrawNative', [item.to, amount]),
});
} else {
callData.add({
to: this.commonCallDataBuilderConfig.vaultAddress,
callData: vaultInterface.encodeFunctionData('withdrawERC20', [
asset.address,
item.to,
amount,
]),
});
}
}

return { callData, value: BigInt(0) };
}
}
10 changes: 4 additions & 6 deletions packages/core/src/lib/workflow/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { WorkflowsFactory } from './factory';
import { PriceTrigger, TimeBasedTrigger, TimeScale } from './triggers';
import type { Execution } from './execution';

export { WorkflowsFactory, PriceTrigger, TimeBasedTrigger, TimeScale };
export type { Execution as WorkflowExecution };
export * from './factory';
export * from './actions';
export * from './triggers';
export type { Execution as WorkflowExecution } from './execution';
3 changes: 2 additions & 1 deletion packages/core/src/lib/workflow/triggers/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { PriceTrigger } from './price-trigger';
import { TimeBasedTrigger } from './time-based-trigger';
import { TimeScale } from './types';
import { InstantTrigger } from './instant-trigger';

export { PriceTrigger, TimeBasedTrigger, TimeScale };
export { PriceTrigger, TimeBasedTrigger, TimeScale, InstantTrigger };

0 comments on commit d7d997e

Please sign in to comment.