Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add sweep function #115

Merged
merged 3 commits into from
Jan 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 141 additions & 0 deletions docs/docs/03-sdk/04-methods-reference/transfer/sweep.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
---
id: sweep
title: sweep
sidebar_position: 3
---

# `sweep`

The `sweep` method generates a quote to transfer the full token balances of source chains to a destination chain.

## Usage

```typescript
import { Sprinter, Environment } from "@chainsafe/sprinter-sdk";

const sprinter = new Sprinter({ baseUrl: Environment.TESTNET });

const settings = {
account: "0x3E101Ec02e7A48D16DADE204C96bFF842E7E2519",
destinationChain: 11155111,
token: "USDC",
};

sprinter.sweep(settings).then((solution) => {
console.log(solution);
});
```

## Parameters

- `settings`: _(Required)_ An object containing the following fields:

- `account`: The user’s address.
- `destinationChain`: The ID of the destination chain.
- `token`: The symbol of the token to be transferred (e.g., `USDC`, `ETH`).
- `recipient?`: _(Optional)_ The address of the recipient of the tokens on the destination chain.
- `sourceChains?`: _(Optional)_ An array of source chain IDs to be considered for the sweep. If omitted, Sprinter will use all available chains for the solution. To limit the solution to a specific chain, provide an array containing only that chain's ID.

- `fetchOptions?`: _(Optional)_ An object containing `baseUrl` to override the default API endpoint for this request.

### Example: Using `sourceChains` for sweeping from specific chains

To get a sweep solution from specific chains, you can set `sourceChains` to an array with chain IDs.

```typescript
const settings = {
account: "0xYourAddressHere",
destinationChain: 11155111, // Sepolia testnet
token: "USDC",
sourceChains: [84532, 137],
};

sprinter.sweep(settings).then((solution) => {
console.log(solution);
});
```

### Example: Using `fetchOptions`

```typescript
sprinter.sweep(settings, { baseUrl: "https://custom.api.url" }).then((solution) => {
console.log(solution);
});
```

## Response

Returns a promise that resolves to a `SolutionResponse`.

```typescript
type SolutionResponse = Array<Solution> | FailedSolution;

interface Solution {
destinationChain: number;
destinationTokenAddress: string;
duration: number; // Time estimate in seconds
fee: Amount;
gasCost: Amount;
senderAddress: string;
sourceChain: number;
sourceTokenAddress: string;
tool: Tool;
transaction: Transaction;
approvals?: Array<Transaction>;
amount: Amount;
}

interface FailedSolution {
error: string;
}
```

### Example Response

import GasTip from "../\_gas-tip.md"

<GasTip />

```json
[
{
"sourceChain": 84532,
"destinationChain": 11155111,
"sourceTokenAddress": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
"destinationTokenAddress": "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
"senderAddress": "0x3E101Ec02e7A48D16DADE204C96bFF842E7E2519",
"tool": {
"name": "Across",
"logoURI": "https://raw.githubusercontent.com/lifinance/types/main/src/assets/icons/bridges/acrossv2.png"
},
"gasCost": {
"amount": "130680140710000",
"amountUSD": 0
},
"fee": {
"amount": "6239846",
"amountUSD": 0
},
"amount": "1178950000",
"duration": 120000000000,
"transaction": {
"data": "0x7b9392320000000000000000000000003e101ec02e7a48d16dade204c96bff842e7e25190000000000000000000000003e101ec02e7a48d16dade204c96bff842e7e2519000000000000000000000000036cbd53842c5426634e7929541ec2318f3dcf7e0000000000000000000000001c7d4b196cb0c7b01d743fbc6116a902379c723800000000000000000000000000000000000000000000000000000000464559700000000000000000000000000000000000000000000000000000000045e6230a0000000000000000000000000000000000000000000000000000000000aa36a70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006780030c000000000000000000000000000000000000000000000000000000006780576c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000001dc0de",
"to": "0x82B564983aE7274c86695917BBf8C99ECb6F0F8F",
"from": "0x3E101Ec02e7A48D16DADE204C96bFF842E7E2519",
"value": "0x0",
"gasLimit": "0x16378",
"chainId": 84532
},
"approvals": [
{
"data": "0x095ea7b300000000000000000000000082b564983ae7274c86695917bbf8c99ecb6f0f8f0000000000000000000000000000000000000000000000000000000046455970",
"to": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
"from": "0x3E101Ec02e7A48D16DADE204C96bFF842E7E2519",
"value": "0x0",
"gasLimit": "0xe484",
"chainId": 84532
}
]
}
]
```
1 change: 1 addition & 0 deletions docs/docs/04-react-sdk/03-using-hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ function YourComponent() {
getUserBalances,
getAvailableTokens,
getAvailableChains,
getSweep,
getTransfer,
getTransferWithHook,
getPoolAssetOnDestination,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ The `useSprinterTransfers` hook provides a simplified interface for generating c
- `getTransferWithHook`: Single-hop token transfers combined with a contract call on the destination chain.
- `getPoolAssetOnDestination`: Aggregates token balances across multiple chains into a single destination.
- `getPoolAssetOnDestinationWithHook`: Aggregates token balances and performs a contract call on the destination chain.
- `getSweep`: A function that generates a quote to transfer the full token balances of source chains to a destination chain

You can trigger any of these methods via the hook to fetch a cross-chain solution.

Expand Down Expand Up @@ -59,6 +60,7 @@ The `useSprinterTransfers` hook returns an object with the following properties:
- **`getTransferWithHook`**: A function that generates a single-hop token transfer combined with a contract call.
- **`getPoolAssetOnDestination`**: A function that generates a solution to aggregate balances from multiple chains into a single destination.
- **`getPoolAssetOnDestinationWithHook`**: A function that generates a solution to aggregate balances and execute a contract call on the destination chain.
- **`getSweep`**: A function that generates a quote to transfer the full token balances of source chains to a destination chain

## Example Response

Expand Down Expand Up @@ -99,5 +101,6 @@ Each method accepts a `settings` parameter, which varies depending on the operat
- **`getTransferWithHook`**: See [SDK Transfer with Contract Call Method Reference](../../sdk/methods-reference/transfer/transfer-with-hook).
- **`getPoolAssetOnDestination`**: See [SDK Pool Asset Method Reference](../../sdk/methods-reference/pool-asset-on-destination/pool-asset-on-destination).
- **`getPoolAssetOnDestinationWithHook`**: See [SDK Pool Asset with Contract Call Method Reference](../../sdk/methods-reference/pool-asset-on-destination/pool-asset-on-destination-with-hook).
- **`getSweep`**: See [Sweep Method Reference](../../sdk/methods-reference/transfer/sweep).

Each method calls the Sprinter SDK's corresponding function and returns the intent-based solution for cross-chain transfers or contract calls.
2 changes: 2 additions & 0 deletions packages/react/lib/context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export function SprinterContext({ children, baseUrl }: SprinterContextProps) {
getTransferWithHook,
getPoolAssetOnDestination,
getPoolAssetOnDestinationWithHook,
getSweep,
} = useTransfers(sprinter);

/** Initialization */
Expand All @@ -85,6 +86,7 @@ export function SprinterContext({ children, baseUrl }: SprinterContextProps) {
getTransferWithHook,
getPoolAssetOnDestination,
getPoolAssetOnDestinationWithHook,
getSweep,
}}
>
{children}
Expand Down
5 changes: 4 additions & 1 deletion packages/react/lib/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export function useSprinterBalances(account: Address) {
const balances: BalancesEntry = _balances[account] || balancesEmptyState;
const getUserBalances = useCallback(
() => _getUserBalances(account),
[_getUserBalances, account]
[_getUserBalances, account],
);

return { balances, getUserBalances };
Expand Down Expand Up @@ -227,6 +227,7 @@ export function useSprinterChains() {
* - `getTransferWithHook`: A function to get a transfer solution that includes an additional contract call on the destination chain.
* - `getPoolAssetOnDestination`: A function to get a solution for pooling assets from multiple chains and transferring them to the destination chain.
* - `getPoolAssetOnDestinationWithHook`: A function to get a solution for pooling assets and performing a contract call on the destination chain.
* - `getSweep`: A function to get a solution for sweeping assets from source chains to a destination chain.
*
* @example
* ```ts
Expand Down Expand Up @@ -269,12 +270,14 @@ export function useSprinterTransfers() {
getTransferWithHook,
getPoolAssetOnDestination,
getPoolAssetOnDestinationWithHook,
getSweep,
} = useSprinter();
return {
solution,
getTransfer,
getTransferWithHook,
getPoolAssetOnDestination,
getPoolAssetOnDestinationWithHook,
getSweep,
};
}
67 changes: 46 additions & 21 deletions packages/react/lib/internal/useTransfers.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,59 @@
import {
type SolutionResponse,
Sprinter,
} from "@chainsafe/sprinter-sdk";
import {useCallback} from "react";
import {useAsyncRequest} from "./useAsyncRequest";
import type {Infer} from "superstruct";
import { type SolutionResponse, Sprinter } from "@chainsafe/sprinter-sdk";
import { useCallback } from "react";
import { useAsyncRequest } from "./useAsyncRequest";
import type { Infer } from "superstruct";
import {
MultiHopSchema,
MultiHopWithContractSchema,
SingleHopSchema, SingleHopWithContractSchema
SingleHopSchema,
SingleHopWithContractSchema,
SweepSchema,
} from "@chainsafe/sprinter-sdk/dist/internal/validators";

export function useTransfers(sprinter: Sprinter) {
const { state: solution, makeRequest } = useAsyncRequest<SolutionResponse>();

const getPoolAssetOnDestination = useCallback((settings: Infer<typeof MultiHopSchema>) => {
makeRequest(sprinter.poolAssetOnDestination(settings));
}, [sprinter, makeRequest]);
const getPoolAssetOnDestination = useCallback(
(settings: Infer<typeof MultiHopSchema>) => {
makeRequest(sprinter.poolAssetOnDestination(settings));
},
[sprinter, makeRequest],
);

const getPoolAssetOnDestinationWithHook = useCallback(
(settings: Infer<typeof MultiHopWithContractSchema>) => {
makeRequest(sprinter.poolAssetOnDestinationWithHook(settings));
},
[sprinter, makeRequest],
);

const getPoolAssetOnDestinationWithHook = useCallback((settings: Infer<typeof MultiHopWithContractSchema>) => {
makeRequest(sprinter.poolAssetOnDestinationWithHook(settings));
}, [sprinter, makeRequest]);
const getTransfer = useCallback(
(settings: Infer<typeof SingleHopSchema>) => {
makeRequest(sprinter.transfer(settings));
},
[sprinter, makeRequest],
);

const getTransfer = useCallback((settings: Infer<typeof SingleHopSchema>) => {
makeRequest(sprinter.transfer(settings));
}, [sprinter, makeRequest]);
const getTransferWithHook = useCallback(
(settings: Infer<typeof SingleHopWithContractSchema>) => {
makeRequest(sprinter.transferWithHook(settings));
},
[sprinter, makeRequest],
);

const getTransferWithHook = useCallback((settings: Infer<typeof SingleHopWithContractSchema>) => {
makeRequest(sprinter.transferWithHook(settings));
}, [sprinter, makeRequest]);
const getSweep = useCallback(
(settings: Infer<typeof SweepSchema>) => {
makeRequest(sprinter.sweep(settings));
},
[sprinter, makeRequest],
);

return { solution, getTransfer, getTransferWithHook, getPoolAssetOnDestination, getPoolAssetOnDestinationWithHook };
return {
solution,
getTransfer,
getTransferWithHook,
getPoolAssetOnDestination,
getPoolAssetOnDestinationWithHook,
getSweep,
};
}
19 changes: 10 additions & 9 deletions packages/react/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { useState } from 'react'
import './App.css'
import {SprinterContext} from "../lib/main.ts";
import {Component} from "./Component.tsx";
import {Action} from "./Action.tsx";
import { useState } from "react";
import "./App.css";
import { SprinterContext } from "../lib/main.ts";
import { Component } from "./Component.tsx";
import { Action } from "./Action.tsx";
import { Environment } from "@chainsafe/sprinter-sdk";

function App() {
const [count, setCount] = useState(0)
const [count, setCount] = useState(0);

return (
<SprinterContext >
<SprinterContext baseUrl={Environment.TESTNET}>
<div>
<Component />
</div>
Expand All @@ -26,7 +27,7 @@ function App() {
Click on the Vite and React logos to learn more
</p>
</SprinterContext>
)
);
}

export default App
export default App;
19 changes: 14 additions & 5 deletions packages/react/src/Component.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
import { useEffect } from "react";
import { useSprinterTokens } from "../lib/hooks.ts";
import { useSprinterTokens, useSprinterTransfers } from "../lib/hooks.ts";

export function Component() {
const hook = useSprinterTokens();
const { getAvailableTokens } = useSprinterTokens();
const { getSweep, solution } = useSprinterTransfers();

useEffect(() => {
hook.getAvailableTokens();
}, [hook]);
getAvailableTokens();
}, [getAvailableTokens]);

return <div>A component</div>;
useEffect(() => {
getSweep({
account: "0x3E101Ec02e7A48D16DADE204C96bFF842E7E2519",
destinationChain: 11155111,
token: "USDC",
});
}, [getSweep]);

return <pre>{JSON.stringify(solution, null, 2)}</pre>;
}
Loading
Loading