Skip to content

Commit

Permalink
Stonfi swap
Browse files Browse the repository at this point in the history
  • Loading branch information
aleksej-paschenko committed Jun 3, 2024
1 parent 52efb39 commit 211a67f
Show file tree
Hide file tree
Showing 3 changed files with 213 additions and 0 deletions.
98 changes: 98 additions & 0 deletions abi/get_methods.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package abi
import (
"context"
"fmt"

"github.com/tonkeeper/tongo/boc"
"github.com/tonkeeper/tongo/tlb"
"github.com/tonkeeper/tongo/ton"
Expand All @@ -23,6 +24,7 @@ var KnownGetMethodsDecoder = map[string][]func(tlb.VmStack) (string, any, error)
"get_collection_data": {DecodeGetCollectionDataResult},
"get_domain": {DecodeGetDomainResult},
"get_editor": {DecodeGetEditorResult},
"get_expected_outputs": {DecodeGetExpectedOutputs_StonfiResult},
"get_full_domain": {DecodeGetFullDomainResult},
"get_jetton_data": {DecodeGetJettonDataResult},
"get_last_clean_time": {DecodeGetLastCleanTimeResult},
Expand All @@ -46,6 +48,7 @@ var KnownGetMethodsDecoder = map[string][]func(tlb.VmStack) (string, any, error)
"get_nominator_data": {DecodeGetNominatorDataResult},
"get_params": {DecodeGetParams_WhalesNominatorResult},
"get_plugin_list": {DecodeGetPluginListResult},
"get_pool_address": {DecodeGetPoolAddress_StonfiResult},
"get_pool_data": {DecodeGetPoolData_StonfiResult, DecodeGetPoolData_TfResult},
"get_pool_full_data": {DecodeGetPoolFullDataResult},
"get_pool_status": {DecodeGetPoolStatusResult},
Expand Down Expand Up @@ -154,6 +157,7 @@ var resultTypes = []interface{}{
&GetCollectionDataResult{},
&GetDomainResult{},
&GetEditorResult{},
&GetExpectedOutputs_StonfiResult{},
&GetFullDomainResult{},
&GetJettonDataResult{},
&GetLastCleanTimeResult{},
Expand All @@ -177,6 +181,7 @@ var resultTypes = []interface{}{
&GetNominatorDataResult{},
&GetParams_WhalesNominatorResult{},
&GetPluginListResult{},
&GetPoolAddress_StonfiResult{},
&GetPoolData_StonfiResult{},
&GetPoolData_TfResult{},
&GetPoolFullDataResult{},
Expand Down Expand Up @@ -669,6 +674,52 @@ func DecodeGetEditorResult(stack tlb.VmStack) (resultType string, resultAny any,
return "GetEditorResult", result, err
}

type GetExpectedOutputs_StonfiResult struct {
Out tlb.Int257
ProtocolFeeOut tlb.Int257
RefFeeOut tlb.Int257
}

func GetExpectedOutputs(ctx context.Context, executor Executor, reqAccountID ton.AccountID, amount tlb.Int257, tokenWallet tlb.MsgAddress) (string, any, error) {
stack := tlb.VmStack{}
var (
val tlb.VmStackValue
err error
)
val = tlb.VmStackValue{SumType: "VmStkInt", VmStkInt: amount}
stack.Put(val)
val, err = tlb.TlbStructToVmCellSlice(tokenWallet)
if err != nil {
return "", nil, err
}
stack.Put(val)

// MethodID = 115709 for "get_expected_outputs" method
errCode, stack, err := executor.RunSmcMethodByID(ctx, reqAccountID, 115709, stack)
if err != nil {
return "", nil, err
}
if errCode != 0 && errCode != 1 {
return "", nil, fmt.Errorf("method execution failed with code: %v", errCode)
}
for _, f := range []func(tlb.VmStack) (string, any, error){DecodeGetExpectedOutputs_StonfiResult} {
s, r, err := f(stack)
if err == nil {
return s, r, nil
}
}
return "", nil, fmt.Errorf("can not decode outputs")
}

func DecodeGetExpectedOutputs_StonfiResult(stack tlb.VmStack) (resultType string, resultAny any, err error) {
if len(stack) != 3 || (stack[0].SumType != "VmStkTinyInt" && stack[0].SumType != "VmStkInt") || (stack[1].SumType != "VmStkTinyInt" && stack[1].SumType != "VmStkInt") || (stack[2].SumType != "VmStkTinyInt" && stack[2].SumType != "VmStkInt") {
return "", nil, fmt.Errorf("invalid stack format")
}
var result GetExpectedOutputs_StonfiResult
err = stack.Unmarshal(&result)
return "GetExpectedOutputs_StonfiResult", result, err
}

type GetFullDomainResult struct {
Domain string
}
Expand Down Expand Up @@ -1524,6 +1575,53 @@ func DecodeGetPluginListResult(stack tlb.VmStack) (resultType string, resultAny
return "GetPluginListResult", result, err
}

type GetPoolAddress_StonfiResult struct {
PoolAddress tlb.MsgAddress
}

func GetPoolAddress(ctx context.Context, executor Executor, reqAccountID ton.AccountID, token0 tlb.MsgAddress, token1 tlb.MsgAddress) (string, any, error) {
stack := tlb.VmStack{}
var (
val tlb.VmStackValue
err error
)
val, err = tlb.TlbStructToVmCellSlice(token0)
if err != nil {
return "", nil, err
}
stack.Put(val)
val, err = tlb.TlbStructToVmCellSlice(token1)
if err != nil {
return "", nil, err
}
stack.Put(val)

// MethodID = 101789 for "get_pool_address" method
errCode, stack, err := executor.RunSmcMethodByID(ctx, reqAccountID, 101789, stack)
if err != nil {
return "", nil, err
}
if errCode != 0 && errCode != 1 {
return "", nil, fmt.Errorf("method execution failed with code: %v", errCode)
}
for _, f := range []func(tlb.VmStack) (string, any, error){DecodeGetPoolAddress_StonfiResult} {
s, r, err := f(stack)
if err == nil {
return s, r, nil
}
}
return "", nil, fmt.Errorf("can not decode outputs")
}

func DecodeGetPoolAddress_StonfiResult(stack tlb.VmStack) (resultType string, resultAny any, err error) {
if len(stack) != 1 || (stack[0].SumType != "VmStkSlice") {
return "", nil, fmt.Errorf("invalid stack format")
}
var result GetPoolAddress_StonfiResult
err = stack.Unmarshal(&result)
return "GetPoolAddress_StonfiResult", result, err
}

type GetPoolData_StonfiResult struct {
Reserve0 tlb.Int257
Reserve1 tlb.Int257
Expand Down
22 changes: 22 additions & 0 deletions abi/schemas/ston-fi.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,28 @@
</output>
</get_method>

<get_method name="get_pool_address">
<input>
<slice name="token0">msgaddress</slice>
<slice name="token1">msgaddress</slice>
</input>
<output version="stonfi" fixed_length="true">
<slice name="pool_address">msgaddress</slice>
</output>
</get_method>

<get_method name="get_expected_outputs">
<input>
<int name="amount">int257</int>
<slice name="token_wallet">msgaddress</slice>
</input>
<output version="stonfi" fixed_length="true">
<int name="out">int257</int>
<int name="protocol_fee_out">int257</int>
<int name="ref_fee_out">int257</int>
</output>
</get_method>

<get_method name="get_pool_data">
<output version="stonfi" fixed_length="true">
<int name="reserve0">int257</int>
Expand Down
93 changes: 93 additions & 0 deletions contract/stonfi/stonfi_swap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package stonfi

import (
"context"
"math/big"

"github.com/tonkeeper/tongo/abi"
"github.com/tonkeeper/tongo/boc"
"github.com/tonkeeper/tongo/contract/jetton"
"github.com/tonkeeper/tongo/liteapi"
"github.com/tonkeeper/tongo/tlb"
"github.com/tonkeeper/tongo/ton"
)

// Stonfi creates a swap message.
type Stonfi struct {
cli *liteapi.Client

router ton.AccountID
master0, token0 ton.AccountID
master1, token1 ton.AccountID
}

func NewStonfi(ctx context.Context, cli *liteapi.Client, router, master0, master1 ton.AccountID) (*Stonfi, error) {
j0 := jetton.New(master0, cli)
token0, err := j0.GetJettonWallet(ctx, router)
if err != nil {
return nil, err
}
j1 := jetton.New(master1, cli)
token1, err := j1.GetJettonWallet(ctx, router)
if err != nil {
return nil, err
}
return &Stonfi{
cli: cli,
router: router,
master0: master0,
token0: token0,
master1: master1,
token1: token1,
}, nil
}

func (s *Stonfi) EstimateMinOut(ctx context.Context, amount big.Int) (*big.Int, error) {
_, value, err := abi.GetPoolAddress(ctx, s.cli, s.router, s.token0.ToMsgAddress(), s.token1.ToMsgAddress())
if err != nil {
return nil, err
}
result, ok := value.(abi.GetPoolAddress_StonfiResult)
if !ok {
return nil, err
}
pool, err := ton.AccountIDFromTlb(result.PoolAddress)
if err != nil {
return nil, err
}
_, output, err := abi.GetExpectedOutputs(context.Background(), s.cli, *pool, tlb.Int257(amount), s.token0.ToMsgAddress())
if err != nil {
return nil, err
}
result2, ok := output.(abi.GetExpectedOutputs_StonfiResult)
if !ok {
return nil, err
}
outputValue := big.Int(result2.Out)
return &outputValue, nil
}

func (s *Stonfi) MakeSwapMessage(attachedTON tlb.Grams, forwardTONAmount tlb.Grams, jettonAmount big.Int, minOut big.Int, address ton.AccountID) (*jetton.TransferMessage, error) {
payload := abi.StonfiSwapJettonPayload{
TokenWallet: s.token1.ToMsgAddress(),
MinOut: tlb.VarUInteger16(minOut),
ToAddress: address.ToMsgAddress(),
}
c := boc.NewCell()
if err := c.WriteUint(0x25938561, 32); err != nil {
return nil, err
}
if err := tlb.Marshal(c, payload); err != nil {
return nil, err
}
jettonTransfer := jetton.TransferMessage{
Sender: address,
Jetton: jetton.New(s.master0, s.cli),
JettonAmount: &jettonAmount,
Destination: s.router,
AttachedTon: attachedTON,
ForwardTonAmount: forwardTONAmount,
ForwardPayload: c,
}
return &jettonTransfer, nil
}

0 comments on commit 211a67f

Please sign in to comment.