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

BOB Gateway v3 SDK #314

Closed
nud3l opened this issue Aug 14, 2024 · 1 comment · Fixed by #318
Closed

BOB Gateway v3 SDK #314

nud3l opened this issue Aug 14, 2024 · 1 comment · Fixed by #318
Assignees
Labels
enhancement New feature or request prio:high Important due to deadlines and/or clear customer needs/benefits.

Comments

@nud3l
Copy link
Contributor

nud3l commented Aug 14, 2024

Is your feature request related to a problem? Please describe.

BOB Gateway is a Bitcoin intent bridge that unlocks Bitcoin liquidity by reducing the number of steps to onboard users, saving time and money. Users can go from BTC on Bitcoin to staked BTC with a single Bitcoin transaction.

Describe the solution you'd like

From a high level, I think we want:

  • Swap API (BTC to wBTC/tBTC/fBTC). In the future, this could also be used for BTC to USDT/USDC/ETH/...
  • Stake API (BTC to solvBTC.BBN/...).

Why separate these two? They will need to account for some of the details under the hood:

  • Swap will need to have a notion to manage slippage/slippage tolerance. Staking doesn't have that issue, since the BTC -> wBTC/tBTC/... swap has a fixed fee.
  • Staking will need to validate address whitelisting. solvBTC.BBN is permissionless, but solvBTC.ENA and some others require whitelisting of the EVM address.

There might be some other differences between the two.

For the APIs themselves, I suggest to stick close to swing:

Swap

Types:

  • TransferParameters: (fromChain: Bitcoin, fromToken: BTC, fromUserAddress: btcAddress, amount: BTC, toChain: BOB, toToken: wBTC/tBTC/..., toUserAddress: evmAddress, maxSlippage: 0.01, gasRefill: ETHAmount)
  • TransferRoute: this would be the Gateway LP contract (selecting the BTC asset on BOB and LP) and optionally the strategy contract.

Flow:

  1. Get quote(TransferParameters) returns possible transfer routes. Right now, we always have a single route on the primary Gateway contracts. But having the API that way will allow us to add strategy contracts to add, say, Sovryn DEX, Velodrome, Oku, ... trading routes for USDC/USDT/... swaps. We might also later on be able to add more destination chains like Arbitrum or Base by integrating Gateway with L0, Hyperlane, and Socket, ... Note: added gasRefill here that swing does not have since we have an ETH swap integration directly in Gateway.
  2. SDK would sort the transfer routes by lowest fees (lowest slippage). Whatever consumes the SDK then selects the route. If we have the cheapest route first, then all they'd need to do is const transferoute = (await get_quote(transferparameters))[0];
  3. Create order (TransferRoute, TransferParameters) creates the order on Gateway. It returns a hash that encodes the details of the order and the EVM address that will receive the funds. This needs to be added to the BTC transaction as a data (OP_RETURN) output.
  4. Send BTC. From the BOB SDK call createTransfer (https://github.com/bob-collective/bob/blob/master/sdk/src/wallet/utxo.ts#L32) with setting the order hash as opReturnData.

Stake

Types:

  • TransferParameters: (fromChain: Bitcoin, fromToken: BTC, fromUserAddress: btcAddress, amount: BTC, toChain: BOB, toToken: solvBTC.BBN, ..., toUserAddress: evmAddress, gasRefill: ETHAmount)
  • TransferRoute: this would be the Gateway LP contract (selecting the BTC asset on BOB and LP) and the strategy contract.

Flow:

  1. Get staking contracts. This should return which staking contracts are available with some details, e.g., solvBTC.BBN, solvBTC.ENA, uniBTC, ...
  2. Get quote(TransferParameters) returns possible transfer routes. It's possible to stake via several LPs. I assume that for each staking asset, there's only one strategy contract that is shared among LPs.
  3. SDK would sort the transfer routes by lowest fees (lowest slippage - only relevant on for the LPs for staking). Whatever consumes the SDK then selects the route. If we have the cheapest route first, then all they'd need to do is const transferoute = (await get_quote(transferparameters))[0];
  4. Create order (TransferRoute, TransferParameters) creates the order on Gateway. It returns a hash that encodes the details of the order and the EVM address that will receive the funds. This needs to be added to the BTC transaction as a data (OP_RETURN) output.
  5. Send BTC. From the BOB SDK call createTransfer (https://github.com/bob-collective/bob/blob/master/sdk/src/wallet/utxo.ts#L32) with setting the order hash as opReturnData.

Comments

For sending the BTC (step 4/5): We should show examples of how to create the Bitcoin transaction with:

  • BitcoinKit (by Dynamic)
  • sats-connect
  • bob-sdk

Open questions

  1. Would be good to understand what details swing returns for the ETH staking contracts, e.g., does it only return the contract address, the name of the protocol (e.g., Lido) and the asset (e.g., stETH) or do they also return APY estimates? @nakul1010 could you have a look at that? Derrek found it; see below.
  2. Do we need to return a time estimate? How do we return a time estimation for the transfer? @gregdhill @nakul1010 any good idea here?
  3. Note: swing combines step 3 and 4 (for swap) and step 4 and 5 (for staking) by requiring apps to pass the Bitcoin wallet connection to the swing SDK. We could do something similar. To be discussed. An advantage to hiding the BTC signing step is that we could easily add both the Bitcoin wallet and the EVM wallet to the BOB SDK and then we could abstract away the steps for staking BTC from Bitcoin or wBTC/tBTC directly from BOB behind the same API interface. @gregdhill @nakul1010 maybe @danielsimao what do you think?
  4. Do we already have transaction states? https://developers.swing.xyz/reference/sdk/staking/deposit#receive-status-updates this is what swing has. I'd assume frontends would want to have something similar if we don't already have this.
@nud3l nud3l added the enhancement New feature or request label Aug 14, 2024
@github-project-automation github-project-automation bot moved this to New 🆕 in Backlog Aug 14, 2024
@nud3l nud3l changed the title BOB Gateway SDK BOB Gateway v3 SDK Aug 14, 2024
@nud3l nud3l added the prio:high Important due to deadlines and/or clear customer needs/benefits. label Aug 14, 2024
@nud3l nud3l moved this from New 🆕 to Todo ⏳ in Backlog Aug 14, 2024
@derrekcoleman
Copy link
Contributor

derrekcoleman commented Aug 14, 2024

Cancelling a Transfer

@gregdhill, how does the server currently handle letting quotes expire? I couldn't find it in server.rs; my guess is it's dropped after some time?

Do you think something like cancelQuote would be nice to have? My guess is it's not worth adding until we're somehow bottlenecked by unfilled quotes reserving too much liquidity.

Fetching Transaction History

We already have getOrders and use it on our UI. Straightforward to extend later if partners ask.

Dom's Open Questions

  1. Swing returns the following interface for its contracts, including staking contracts. Notice the lack of APY.
interface Contract {
  id: string; // Unique Swing Identifier
  type: 'deposit' | 'withdraw';
  address: string; // Deployed contract address
  method: string; // Contract method (eg. deposit, withdraw)
  chain: string;
 
  inputToken: Token; // Token you send to the contract
  outputToken: Token | null; // Token you receive from the contract
 
  // Swing's integration provider
  integration: {
    type: 'staking';
    slug: string;
    name: string;
    logo: string;
    monetization: boolean;
  };
}
  1. We could return a time estimate, but maybe Status Update codes are good enough (see the top of this message).
  2. (No opinion from me on passing the Bitcoin wallet into our SDK)
  3. Strong agree. Pasting their Swap example here for visibility. (Stake is the same except it lacks the WALLET_CONNECTION_REQUIRED case, strangely.)
swingSDK.on('TRANSFER', (transferStep, transferResults) => {
  switch (transferStep.status) {
    case 'PENDING':
      // Let the user know the step is pending: `transferStep.step`
      break;
 
    case 'WALLET_CONNECTION_REQUIRED':
      // Handle connecting wallets using your favorite library like Wagmi
      // or alert the user to do it manually.
      // Example: await connectWallet(transferStep.chain);
      break;
 
    case 'CHAIN_SWITCH_REQUIRED':
      // Handle switching chains using your favorite library like Wagmi
      // or alert the user to do it manually
      // Example: await switchNetwork(transferStep.chain.chainId);
      break;
 
    case 'ACTION_REQUIRED':
      // Let the user know they need to take action within their wallet, such as signing a transaction
      break;
 
    case 'CONFIRMING':
      // Let the user know the transaction is waiting for confirmations
      break;
 
    case 'SUCCESS':
      // The transaction was successful, yay!
      break;
 
    case 'FAILED':
      // Alert the user there was an error. Check the message in `transferStep.error`
      break;
  }
});

@github-project-automation github-project-automation bot moved this from Todo ⏳ to Done ✅ in Backlog Aug 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request prio:high Important due to deadlines and/or clear customer needs/benefits.
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

4 participants