Skip to content

Commit

Permalink
docs: cross-chain message guide (#42)
Browse files Browse the repository at this point in the history
  • Loading branch information
dohaki authored Oct 8, 2024
1 parent 1c6a1aa commit 01b35b8
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 6 deletions.
126 changes: 122 additions & 4 deletions packages/sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ To learn more visit our [docs](https://docs.across.to/).

## Installation

To get started, install the integrator sdk and its peer dependency [viem](https://viem.sh/).
To get started, install the app sdk and its peer dependency [viem](https://viem.sh/).

```bash
pnpm i @across-protocol/app-sdk viem
Expand Down Expand Up @@ -108,11 +108,129 @@ The method will execute a quote by:
You can use the `onProgress` callback to act on different stages of the execution.
Have a look at our [example app](../../apps/example) for a more detailed usage of this method.

## Deposit details
## Cross-chain message handling

TODO
Across enables users to seamlessly interact with your dApp or chain using assets from other chains.

## Cross-chain message handling
### 1. Craft a cross-chain message

To implement this feature, you first need to specify a `crossChainMessage`.
The example below shows a cross-chain message for staking USDC into a contract deployed
on Optimism by:

1. Approve USDC to be pulled into staking
2. Stake approved amount into contract

```ts
// Example staking contract on Optimism
const stakingContractAddress = "0x733Debf51574c70CfCdb7918F032E16F686bd9f8";
// USDC on Optimism
const usdcAddress = "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85";
// Example user address
const userAddress = "0x924a9f036260DdD5808007E1AA95f08eD08aA569a";
const inputAmount = parseUnits("200", 6);

const crossChainMessage = {
// This address will receive the amount of bridged tokens on the destination chain if
// one of the cross-chain actions fail. Leftover tokens are here as well if all actions
// succeed.
fallbackRecipient: userAddress,
// List of actions that should be executed on the destination chain
actions: [
{
// Address of target contract on destination chain, i.e. USDC on Optimism
target: usdcAddress,
// Encoded function data, i.e. calldata for approving USDC to be pulled in by
// staking contract
callData: generateApproveCallData(
stakingContractAddress,
inputAmount
),
// Native msg.value, can be 0 in the context of USDC
value: 0n,
// Update call data callback - we need to provide a callback function to
// re-generate calldata because it depends on the `outputAmount`, i.e.
// `inputAmount` - `relayer fee`. This is the amount the user has available after a
// relayer filled the deposit on the destination chain.
updateCallData: (outputAmount) => generateApproveCallData(
stakingContractAddress,
outputAmount
)
},
{
// Address of target contract on destination chain, i.e. staking contract
// on Optimism
target: stakingContractAddress,
// Encoded function data, i.e. calldata for staking USDC on behalf of user
callData: generateStakeCallData(
userAddress,
inputAmount
)
// Native msg.value, can be 0 in the context of USDC
value: 0n,
// Same reasoning as above in the approve step.
updateCallData: (outputAmount) => generateStakeCallData(
stakingContractAddress,
outputAmount
)
}
]
}

function generateApproveCallData(spender: Address, amount: uint256) {
const approveCallData = encodeFunctionData({
abi: [parseAbiItem("function approve(address spender, uint256 value)")],
args: [spender, amount],
});

return approveCallData;
}

function generateStakeCallData(userAddress: Address, amount: uint256) {
return encodeFunctionData({
abi: [parseAbiItem("function stake(address stakerAddress, uint256 amount")],
args: [userAddress, amount],
});
}
```

### 2. Retrieve a quote

After specifying a cross-chain message, you simply can fetch a quote the same way as a normal bridge

```ts
const route = {
originChainId: arbitrum.chainId
destinationChainId: optimism.chainId,
inputToken: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
outputToken: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",
};
const quote = await client.getQuote({
route,
inputAmount,
crossChainMessage // crated above
});
```

### 3. Execute a quote

If the quote is available, you can execute like so

```ts
import { useWalletClient } from "wagmi";

const wallet = useWalletClient();

await client.executeQuote({
walletClient: wallet,
deposit: quote.deposit, // returned by `getQuote`
onProgress: (progress) => {
// handle progress
},
});
```

## Deposit details

TODO

Expand Down
20 changes: 18 additions & 2 deletions packages/sdk/src/actions/getQuote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,11 +160,27 @@ export async function getQuote(params: GetQuoteParams): Promise<Quote> {
// If a given cross-chain message is dependent on the outputAmount, update it
if (crossChainMessage && typeof crossChainMessage === "object") {
for (const action of crossChainMessage.actions) {
if (action.update) {
const { callData, value } = action.update(outputAmount);
if (action.update || action.updateCallData || action.updateValue) {
let callData: Hex;
let value: bigint;

if (action.update) {
const updated = action.update(outputAmount);
callData = updated.callData;
value = updated.value;
} else {
callData = action.updateCallData
? action.updateCallData(outputAmount)
: action.callData;
value = action.updateValue
? action.updateValue(outputAmount)
: BigInt(action.value);
}
action.callData = callData;
action.value = value;

logger?.debug("Updated calldata:", action.callData);
logger?.debug("Updated value:", action.value);
}
}
message = buildMulticallHandlerMessage({
Expand Down
2 changes: 2 additions & 0 deletions packages/sdk/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export type CrossChainAction = {
callData: Hex;
value: Amount;
update?: (outputAmount: bigint) => { callData: Hex; value: bigint };
updateCallData?: (outputAmount: bigint) => Hex;
updateValue?: (outputAmount: bigint) => bigint;
};

export type IndexerStatusResponse = {
Expand Down

0 comments on commit 01b35b8

Please sign in to comment.