solana meteora dlmm协议对接golang版本

最近我开发了solana上的去中心化交易所,meteora的dlmm池子的交易协议对接,用的是golang语言,下面我详细讲解一下。期初我们想通过程序对对接meteoradlmm池子,但是找遍github,发现只有typescript版本的,跟我们的技术栈不一样,以后不好维护,我们的技术栈是

最近我开发了solana上的去中心化交易所,meteora的dlmm池子的交易协议对接,用的是golang语言,下面我详细讲解一下。

起初我们想通过程序对对接meteora dlmm池子,但是找遍github,发现只有typescript版本的,跟我们的技术栈不一样,以后不好维护,我们的技术栈是golang,于是我开始着手翻译typescript SDK。

目前我们实现了如下功能:

  • 基于输入数量,计算输出数量
  • 基于滑点,计算最小输出数量
  • 执行兑换

整个翻译过程很痛苦,因为dlmm的计算比传统的amm计算复杂太多,期初我是安排技术小哥开发,技术小哥研究了一个月,说不好搞,需要精通ts语言和golang语言,才能顺利翻译。

后来我自己通过ts版本sdk,翻译成golang,并于近期翻译完成,通过大量测试,发现和官方sdk计算的分毫不差,和meteora前端网页显示的也是分毫不差,和jupiter聚合器显示的也是分毫不差,最终正确完成。

整个项目结构如下:

image.png 其中:

  • main.go是测试启动文件
  • constant文件夹存放一些常量,包括:程序ID、代币账号、协议常量等
  • helper文件夹存放详细报价计算、手续费计算等
  • lb_clmm文件夹保存通过idl文件转成的go文件
  • index.go是计算兑换数量的
  • pool.go是获取池子数据并解析的
  • swap.go是详细兑换部分

下面是main.go测试部分:

package main

import (
    "context"
    "fmt"

    "github.com/gagliardetto/solana-go"
    "github.com/shopspring/decimal"

    "tradebot/pkg/meteora_dlmm"
    "tradebot/pkg/meteora_dlmm/constant"
)

func main() {
    // rpc节点
    httpsRpc := ""
    wssRpc := ""

    // DLMM program账号
    DLMMProgramID := constant.DLMMProgramID
    // 池子账号
    poolAccount := solana.MustPublicKeyFromBase58("G7ixPyiyNeggVf1VanSetFMNbVuVCPtimJmd9axfQqng")
    // 私钥
    privateKey := solana.MustPrivateKeyFromBase58("")

    // 交易from地址
    toToken := "27G8MtK7VtTcCHkpASjSDdkWWYfoqT6ggEuKidVJidD4"
    // 交易to地址
    fromToken := "So11111111111111111111111111111111111111112"
    // 交易数量,已包含decimals(如果出现输出数量为0,请提高inAmount)
    inAmount := decimal.NewFromInt(100000)
    // 允许的滑点,这里的30代表0.003,表示0.3%,30个基点
    allowedSlippage := decimal.NewFromInt(30)
    // 优先费
    yxf := uint64(1)
    // jito小费
    jitoAmount := uint64(0)
    // jito小费账号,当小费不为空的情况下,该地址不能为空,请到jito官方文档查看小费地址列表,随机找个小费地址
    jitoAccount := solana.PublicKey{}

    dlmm := meteora_dlmm.NewDLMM(poolAccount, DLMMProgramID, privateKey, httpsRpc, wssRpc)

    // 初始化池子,获取池子详细数据
    dlmm.GetPoolInfo()

    var swapForY bool

    // 计算兑换方向
    lbPair := dlmm.GetLbPair()
    if fromToken == lbPair.TokenXMint.String() {
        swapForY = true
    }

    binArrayAccount, err := dlmm.GetBinArrayForSwap(context.Background(), swapForY, 4)
    if err != nil {
        panic(err)
    }

    // remaining account,用于添加到交易的账号列表中
    for _, v := range binArrayAccount {
        dlmm.SetRemainingAccount(v.PublicKey)
    }

    swapQuote, err := dlmm.SwapQuote(inAmount.BigInt(), swapForY, allowedSlippage.BigInt(), binArrayAccount, true)
    if err != nil {
        panic(err)
    }

    fmt.Printf("计算结果:inAmount=%d,OutAmount=%d,MinOutAmount=%d\n",
        inAmount.BigInt(), swapQuote.OutAmount, swapQuote.MinOutAmount)

    // 执行兑换
    signature, err := dlmm.Swap(inAmount.BigInt().Uint64(), swapQuote.MinOutAmount.Uint64(),
        fromToken, toToken, yxf, jitoAmount, jitoAccount)
    if err != nil {
        panic(err)
    }

    fmt.Println("交易成功,signature:", signature)
}

实际的计算极为复杂,例如:

image.png

目前这套代码用于我们的交易机器人,用来对接meteora dlmm池子。 其实这个和raydium clmm池子类似,clmm池子翻译也很复杂,期初我们用的是ts版本的sdk做的,但是集成到项目中,会遇到一些问题,由于我们的技术栈限制,无法便捷修改代码,导致很被动。

感兴趣的朋友可以一起讨论下,有任何问题也可以进行评论,我看到都会一一解答,对于solana感兴趣的朋友,也可以一起讨论。

接下来继续完善本文档涉及到的知识点。

  • 原创
  • 学分: 0
  • 分类: Solana
  • 标签:
点赞 0
收藏 0
分享

0 条评论

请先 登录 后评论
加密曙光
加密曙光
0xADd4...8F00
区块链爱好者,研究员,微信:kevin76702,我们的机器人站点:https://product-bot.gitbook.io/aurora-dev