From a72df37787c1667dd8b85d40da58a74a52e27bd8 Mon Sep 17 00:00:00 2001 From: Alexander Hasselbach Date: Sun, 31 May 2026 23:51:44 +0300 Subject: [PATCH] defi assets: added jetton preview for jetton/toncoin in a liquidity pool --- api/openapi.json | 39 +++- api/openapi.yml | 29 ++- go.mod | 10 +- go.sum | 20 +- internal/g/hash.go | 14 ++ pkg/api/defi_converters.go | 37 ++-- pkg/api/jetton_converters.go | 2 +- pkg/api/jetton_handlers.go | 4 +- pkg/core/price.go | 7 + pkg/defi/asset_info.go | 193 ------------------ pkg/defi/asset_info_test.go | 85 -------- pkg/defi/assets.go | 159 ++++++++++++++- pkg/defi/dedust/dedust.go | 55 ++++++ pkg/defi/evaa/evaa.go | 6 +- pkg/defi/handler.go | 18 ++ pkg/defi/stonfi/stonfi.go | 89 +++++++++ pkg/defi/{asset.go => types.go} | 36 ++-- pkg/defi/whales/whales.go | 12 +- pkg/litestorage/dedust.go | 2 +- pkg/oas/oas_json_gen.go | 333 ++++++++++++++++++++++++++------ pkg/oas/oas_schemas_gen.go | 260 +++++++++++++++++++------ pkg/oas/oas_validators_gen.go | 112 +++++++++-- 22 files changed, 1013 insertions(+), 509 deletions(-) create mode 100644 internal/g/hash.go delete mode 100644 pkg/defi/asset_info.go delete mode 100644 pkg/defi/asset_info_test.go create mode 100644 pkg/defi/dedust/dedust.go create mode 100644 pkg/defi/handler.go create mode 100644 pkg/defi/stonfi/stonfi.go rename pkg/defi/{asset.go => types.go} (55%) diff --git a/api/openapi.json b/api/openapi.json index 1f668fabe..ac2ae5234 100644 --- a/api/openapi.json +++ b/api/openapi.json @@ -3179,9 +3179,6 @@ "format": "address", "type": "string" }, - "asset_type": { - "$ref": "#/components/schemas/DefiAssetAssetType" - }, "defi_provider": { "$ref": "#/components/schemas/DefiProvider" }, @@ -3191,17 +3188,20 @@ "pool_address": { "format": "address", "type": "string" + }, + "type": { + "$ref": "#/components/schemas/DefiAssetType" } }, "required": [ - "asset_type", + "type", "amount", "defi_provider", "locked_asset" ], "type": "object" }, - "DefiAssetAssetType": { + "DefiAssetType": { "enum": [ "staking", "lending_supply", @@ -3226,6 +3226,21 @@ ], "type": "object" }, + "DefiLiquidPoolAssets": { + "properties": { + "asset0": { + "$ref": "#/components/schemas/DefiLockedAsset" + }, + "asset1": { + "$ref": "#/components/schemas/DefiLockedAsset" + } + }, + "required": [ + "asset0", + "asset1" + ], + "type": "object" + }, "DefiLockedAsset": { "properties": { "jetton": { @@ -4037,8 +4052,14 @@ "defi_provider": { "$ref": "#/components/schemas/DefiProvider" }, + "pool_assets": { + "$ref": "#/components/schemas/DefiLiquidPoolAssets" + }, "token_type": { - "$ref": "#/components/schemas/DefiAssetAssetType" + "$ref": "#/components/schemas/DefiAssetType" + }, + "type": { + "$ref": "#/components/schemas/DefiAssetType" } }, "required": [ @@ -4054,6 +4075,9 @@ "type": "string", "x-js-format": "bigint" }, + "defi_asset": { + "$ref": "#/components/schemas/JettonAssetInfo" + }, "extensions": { "example": [ "custom_payload", @@ -4522,9 +4546,6 @@ "format": "address", "type": "string" }, - "asset_info": { - "$ref": "#/components/schemas/JettonAssetInfo" - }, "custom_payload_api_uri": { "type": "string" }, diff --git a/api/openapi.yml b/api/openapi.yml index f90a4d40e..29216f825 100644 --- a/api/openapi.yml +++ b/api/openapi.yml @@ -6073,18 +6073,31 @@ components: $ref: '#/components/schemas/ScaledUI' description: type: string - asset_info: - $ref: '#/components/schemas/JettonAssetInfo' JettonAssetInfo: type: object required: - token_type - defi_provider properties: + # use type token_type: - $ref: '#/components/schemas/DefiAssetAssetType' + $ref: '#/components/schemas/DefiAssetType' + type: + $ref: '#/components/schemas/DefiAssetType' defi_provider: $ref: '#/components/schemas/DefiProvider' + pool_assets: + $ref: '#/components/schemas/DefiLiquidPoolAssets' + DefiLiquidPoolAssets: + type: object + required: + - asset0 + - asset1 + properties: + asset0: + $ref: '#/components/schemas/DefiLockedAsset' + asset1: + $ref: '#/components/schemas/DefiLockedAsset' ScaledUI: type: object required: @@ -6116,6 +6129,8 @@ components: $ref: '#/components/schemas/AccountAddress' jetton: $ref: '#/components/schemas/JettonPreview' + defi_asset: + $ref: '#/components/schemas/JettonAssetInfo' extensions: type: array items: @@ -8181,7 +8196,7 @@ components: type: array items: $ref: '#/components/schemas/DefiAsset' - DefiAssetAssetType: + DefiAssetType: type: string enum: - staking @@ -8193,13 +8208,13 @@ components: DefiAsset: type: object required: - - asset_type + - type - amount - defi_provider - locked_asset properties: - asset_type: - $ref: '#/components/schemas/DefiAssetAssetType' + type: + $ref: '#/components/schemas/DefiAssetType' amount: type: string x-js-format: bigint diff --git a/go.mod b/go.mod index b6dcbd3d8..2f5c8081d 100644 --- a/go.mod +++ b/go.mod @@ -23,13 +23,13 @@ require ( github.com/sourcegraph/conc v0.3.0 github.com/stretchr/testify v1.11.1 github.com/tonkeeper/scam_backoffice_rules v0.0.11 - github.com/tonkeeper/tongo v1.22.20 + github.com/tonkeeper/tongo v1.22.30 go.opentelemetry.io/otel v1.43.0 go.opentelemetry.io/otel/metric v1.43.0 go.opentelemetry.io/otel/trace v1.43.0 go.uber.org/zap v1.27.1 - golang.org/x/exp v0.0.0-20260603202125-055de637280b - golang.org/x/net v0.55.0 + golang.org/x/exp v0.0.0-20260611194520-c48552f49976 + golang.org/x/net v0.56.0 golang.org/x/sync v0.21.0 golang.org/x/text v0.38.0 google.golang.org/grpc v1.80.0 @@ -62,9 +62,9 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect golang.org/x/crypto v0.53.0 // indirect - golang.org/x/mod v0.36.0 // indirect + golang.org/x/mod v0.37.0 // indirect golang.org/x/sys v0.46.0 // indirect - golang.org/x/tools v0.45.0 // indirect + golang.org/x/tools v0.46.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 // indirect google.golang.org/protobuf v1.36.11 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index c9701ed2c..6481ca93d 100644 --- a/go.sum +++ b/go.sum @@ -97,8 +97,8 @@ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/tonkeeper/scam_backoffice_rules v0.0.11 h1:VXbNNyTO49OArvQwPRCU+1WUEyfQgkqG7Q8NVhQ7320= github.com/tonkeeper/scam_backoffice_rules v0.0.11/go.mod h1:SqZXYO9vbID8ku+xnnaKXeNGmehxigODGrk5V1KqbRA= -github.com/tonkeeper/tongo v1.22.20 h1:dr7q+lJp+3vO1BLWG5cyRgKGwdb66zoJ5zsWCqaF7wY= -github.com/tonkeeper/tongo v1.22.20/go.mod h1:nHmdEXPfT0/EvkEaBzPiY599/0OYjQSW4dWR7aX+OII= +github.com/tonkeeper/tongo v1.22.30 h1:OpS39mqoYjehmf15MB3QjZ7QQBiic3nzNlEkE+v5m6k= +github.com/tonkeeper/tongo v1.22.30/go.mod h1:nHmdEXPfT0/EvkEaBzPiY599/0OYjQSW4dWR7aX+OII= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= @@ -123,12 +123,12 @@ go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto= golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio= -golang.org/x/exp v0.0.0-20260603202125-055de637280b h1:v1uXiEBHo8QA0LiGCo7UgHMzHT4Kdfpl2zmtH5vaP1Q= -golang.org/x/exp v0.0.0-20260603202125-055de637280b/go.mod h1:d2fgXJLVs4dYDHUk5lwMIfzRzSrWCfGZb0ZqeLa/Vcw= -golang.org/x/mod v0.36.0 h1:JJjpVx6myfUsUdAzZuOSTTmRE0PfZeNWzzvKrP7amb4= -golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ= -golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8= -golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww= +golang.org/x/exp v0.0.0-20260611194520-c48552f49976 h1:X8Hz2ImujgbmetVuW+w2YkyZChE3cBpZi2P158rTG9M= +golang.org/x/exp v0.0.0-20260611194520-c48552f49976/go.mod h1:vnf4pv9iKZXY58sQE1L86zmNWJ4159e1RkcWiLCkeEY= +golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ= +golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0= +golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o= +golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec= golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM= golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -136,8 +136,8 @@ golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw= golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE= golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4= -golang.org/x/tools v0.45.0 h1:18qN3FAooORvApf5XjCXgsuayZOEtXf6JK18I3+ONa8= -golang.org/x/tools v0.45.0/go.mod h1:LuUGqqaXcXMEFEruIVJVm5mgDD8vww/z/SR1gQ4uE/0= +golang.org/x/tools v0.46.0 h1:7jTurBkPZu4moS/Uy4OQT1M+QBlsj3wejyZwsT8Z7rk= +golang.org/x/tools v0.46.0/go.mod h1:FrD85F8l+NWL+9XWBSyVSHO6Ne4jutsfIFba7AWQ5Ys= google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 h1:m8qni9SQFH0tJc1X0vmnpw/0t+AImlSvp30sEupozUg= google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= diff --git a/internal/g/hash.go b/internal/g/hash.go new file mode 100644 index 000000000..a44b3cf6a --- /dev/null +++ b/internal/g/hash.go @@ -0,0 +1,14 @@ +package g + +import ( + "encoding/base64" + "encoding/hex" +) + +func MustHex2Base64(hexHash string) string { + b, err := hex.DecodeString(hexHash) + if err != nil { + panic(err) + } + return base64.StdEncoding.EncodeToString(b) +} diff --git a/pkg/api/defi_converters.go b/pkg/api/defi_converters.go index 9e0290270..29313dbd8 100644 --- a/pkg/api/defi_converters.go +++ b/pkg/api/defi_converters.go @@ -31,8 +31,8 @@ func (h *Handler) GetAccountDefiAssets(ctx context.Context, params oas.GetAccoun func (h *Handler) convertDefiAsset(ctx context.Context, asset defi.Asset) oas.DefiAsset { result := oas.DefiAsset{ - AssetType: convertDefiAssetType(asset.Type), - Amount: asset.Amount, + Type: convertDefiAssetType(asset.Type), + Amount: asset.LockedAsset.Amount.String(), DefiProvider: h.convertDefiProvider(asset.Provider), LockedAsset: h.convertDefiLockedAsset(ctx, asset.LockedAsset), } @@ -45,16 +45,16 @@ func (h *Handler) convertDefiAsset(ctx context.Context, asset defi.Asset) oas.De return result } -var defi2oasMap = map[defi.AssetType]oas.DefiAssetAssetType{ - defi.AssetTypeStaking: oas.DefiAssetAssetTypeStaking, - defi.AssetTypeLiquidStaking: oas.DefiAssetAssetTypeLiquidStaking, - defi.AssetTypeLiquidPool: oas.DefiAssetAssetTypeLiquidPool, - defi.AssetTypeYieldToken: oas.DefiAssetAssetTypeYieldToken, - defi.AssetTypeLendingSupply: oas.DefiAssetAssetTypeLendingSupply, - defi.AssetTypeLendingBorrow: oas.DefiAssetAssetTypeLendingBorrow, +var defi2oasMap = map[defi.AssetType]oas.DefiAssetType{ + defi.AssetTypeStaking: oas.DefiAssetTypeStaking, + defi.AssetTypeLiquidStaking: oas.DefiAssetTypeLiquidStaking, + defi.AssetTypeLiquidPool: oas.DefiAssetTypeLiquidPool, + defi.AssetTypeYieldToken: oas.DefiAssetTypeYieldToken, + defi.AssetTypeLendingSupply: oas.DefiAssetTypeLendingSupply, + defi.AssetTypeLendingBorrow: oas.DefiAssetTypeLendingBorrow, } -func convertDefiAssetType(assetType defi.AssetType) oas.DefiAssetAssetType { +func convertDefiAssetType(assetType defi.AssetType) oas.DefiAssetType { if oasType, ok := defi2oasMap[assetType]; ok { return oasType } @@ -80,19 +80,22 @@ func (h *Handler) convertDefiJettonPreview(ctx context.Context, master ton.Accou return jettonPreview(master, meta, score, nil) } -func (h *Handler) optJettonAssetInfo(info defi.AssetInfo, ok bool) *oas.JettonAssetInfo { +func (h *Handler) optJettonAssetInfo(ctx context.Context, info defi.AssetInfo, ok bool) *oas.JettonAssetInfo { if !ok { return nil } - converted := h.convertJettonAssetInfo(info) - return &converted -} - -func (h *Handler) convertJettonAssetInfo(info defi.AssetInfo) oas.JettonAssetInfo { - return oas.JettonAssetInfo{ + result := oas.JettonAssetInfo{ TokenType: convertDefiAssetType(info.TokenType), DefiProvider: h.convertDefiProvider(info.DefiProvider), } + if info.LiquidityPool != nil { + result.PoolAssets = oas.NewOptDefiLiquidPoolAssets(oas.DefiLiquidPoolAssets{ + Asset0: h.convertDefiLockedAsset(ctx, info.LiquidityPool.Asset0), + Asset1: h.convertDefiLockedAsset(ctx, info.LiquidityPool.Asset1), + }) + } + converted := result + return &converted } func (h *Handler) convertDefiProvider(provider defi.Provider) oas.DefiProvider { diff --git a/pkg/api/jetton_converters.go b/pkg/api/jetton_converters.go index 036f92a12..2758e5232 100644 --- a/pkg/api/jetton_converters.go +++ b/pkg/api/jetton_converters.go @@ -212,7 +212,7 @@ func (h *Handler) convertJettonBalance(ctx context.Context, wallet core.JettonWa score, _ := h.score.GetJettonScore(wallet.JettonAddress) jettonBalance.Jetton = jettonPreview(wallet.JettonAddress, normalizedMetadata, score, scaledUiParams) if assetInfo != nil { - jettonBalance.Jetton.AssetInfo.SetTo(*assetInfo) + jettonBalance.DefiAsset.SetTo(*assetInfo) } return jettonBalance, nil diff --git a/pkg/api/jetton_handlers.go b/pkg/api/jetton_handlers.go index c505c34fe..6963f8843 100644 --- a/pkg/api/jetton_handlers.go +++ b/pkg/api/jetton_handlers.go @@ -42,7 +42,7 @@ func (h *Handler) GetAccountJettonsBalances(ctx context.Context, params oas.GetA } for _, wallet := range wallets { assetInfo, ok := assetInfos[wallet.JettonAddress] - jettonBalance, err := h.convertJettonBalance(ctx, wallet, params.Currencies, nil, h.optJettonAssetInfo(assetInfo, ok)) + jettonBalance, err := h.convertJettonBalance(ctx, wallet, params.Currencies, nil, h.optJettonAssetInfo(ctx, assetInfo, ok)) if err != nil { h.logger.Warn(fmt.Sprintf("Failed to convert jetton balance for wallet %v", wallet.JettonAddress.ToRaw()), zap.Error(err)) continue @@ -76,7 +76,7 @@ func (h *Handler) GetAccountJettonBalance(ctx context.Context, params oas.GetAcc assetInfos = defi.AssetInfos(ctx, h.storage, h.logger, []tongo.AccountID{wallets[0].JettonAddress}) } assetInfo, ok := assetInfos[wallets[0].JettonAddress] - jettonBalance, err := h.convertJettonBalance(ctx, wallets[0], params.Currencies, nil, h.optJettonAssetInfo(assetInfo, ok)) + jettonBalance, err := h.convertJettonBalance(ctx, wallets[0], params.Currencies, nil, h.optJettonAssetInfo(ctx, assetInfo, ok)) if err != nil { return nil, err } diff --git a/pkg/core/price.go b/pkg/core/price.go index 97f4feff9..840bfbbed 100644 --- a/pkg/core/price.go +++ b/pkg/core/price.go @@ -37,3 +37,10 @@ func PriceNanoGram(amount int64) Price { Amount: *big.NewInt(amount), } } + +func NewCurrencyJetton(master *tongo.AccountID) Currency { + return Currency{ + Type: CurrencyJetton, + Jetton: master, + } +} diff --git a/pkg/defi/asset_info.go b/pkg/defi/asset_info.go deleted file mode 100644 index cd0d5ba39..000000000 --- a/pkg/defi/asset_info.go +++ /dev/null @@ -1,193 +0,0 @@ -package defi - -import ( - "context" - _ "embed" - "encoding/base64" - "encoding/hex" - - "github.com/tonkeeper/opentonapi/internal/g" - "github.com/tonkeeper/opentonapi/pkg/core" - "github.com/tonkeeper/opentonapi/pkg/references" - "github.com/tonkeeper/tongo" - "github.com/tonkeeper/tongo/ton" - "go.uber.org/zap" -) - -type Provider struct { - Name string `json:"name"` - Description string `json:"description"` - Link string `json:"link"` - MiniappLink string `json:"miniapp_link"` - Icon string `json:"icon"` - Card string `json:"card"` - Full string `json:"full"` - Tag string `json:"tag"` -} - -type AssetInfo struct { - TokenType AssetType - DefiProvider Provider -} - -type jettonAssetDumpItem struct { - TokenType AssetType `json:"token_type"` - Provider string `json:"provider"` -} - -const ( - stonfiProviderID = "stonfi" - dedustProviderID = "dedust" -) - -type JettonMasterSource interface { - GetJettonMastersByAddresses(ctx context.Context, addresses []ton.AccountID) ([]core.JettonMaster, error) -} - -//go:embed defi_masters_mapping.json -var jettonAssetDump []byte - -//go:embed defi_providers.json -var jettonProvidersDump []byte - -var jettonAssetDumpInfos map[tongo.AccountID]AssetInfo -var jettonDefiProviders map[string]Provider - -func init() { - jettonDefiProviders = g.MustParseJson[map[string]Provider](jettonProvidersDump) - jettonAssetDumpInfos = parseJettonAssetDump(jettonAssetDump, jettonDefiProviders) -} - -var stonfiPoolCodeHashes = map[string]bool{ - // STON.fi v1 pool, e.g. https://app.ston.fi/pools/0:1b011c80e68e5942aab7e5c79b7b4faacd4999ecda9579df58b3edfbcca414f4 - mustBase64Hash("82566ad72b6568fe7276437d3b0c911aab65ed701c13601941b2917305e81c11"): true, - // STON.fi v2 constant product pool, e.g. https://app.ston.fi/pools/0:8649cad97b5c5bc96a960ef748ea6ccff8601c01616fe995ee6893ae4aa7a6c6 - mustBase64Hash("ec614ea4aaea3f7768606f1c1632b3374d3de096a1e7c4ba43c8009c487fee9d"): true, - // STON.fi v2 stableswap pool, e.g. https://app.ston.fi/pools/0:022cdbe42ffd83d97056fd72aa1b26cf46479be544599edb0423abc5c737070b - mustBase64Hash("f04a14c3231221056c3499965e4604417e324f8e9121d840120d803288715594"): true, - // STON.fi v2 stableswap pool, e.g. https://app.ston.fi/pools/0:52518e14586245029b342b01d8e2da4e1aacd4e350d9872ad3f0ebb20165ad9d - mustBase64Hash("fbc7e8fcca72c2b9c078b359ffa936f46384491b895b6577b0a6cb3f569040bc"): true, - // STON.fi v2 weighted stableswap pool, e.g. https://app.ston.fi/pools/0:05ea635b2a168cadfca174d72b12744a5b57d70378e6912e8a33b6b39bd3ee9d - mustBase64Hash("dac47636ae899081ebd4f47dc90ef9de98456b1000591069773f683c6d601fa9"): true, - // STON.fi v2 constant product pool, e.g. https://app.ston.fi/pools/0:ad28d3fb6e911349282352604ab89ad6f3272f9aa2dc73276588f338eec3d823 - mustBase64Hash("cf5d0b99fa704e7cf2c9d50a8ff8b8bc7ce0b8a74e414b9c279ac544e7aade05"): true, -} - -var dedustPoolCodeHashes = map[string]bool{ - // DeDust pool, e.g. https://dedust.io/pools/0:00576440c4a6f443af2fcef7b27a2277eb0c552e8b898190cce9c3393d17c6e5 - mustBase64Hash("778f0d3fe6482c50888970df5e787f40f3a4ab282170c035a5920877058c99d3"): true, - // DeDust pool, e.g. https://dedust.io/pools/0:011e4c677529eaac180c20347bdcb0741410c33340bf529dfd10bd519f76a8ff - mustBase64Hash("1275095b6da3911292406f4f4386f9e780099b854c6dee9ee2895ddce70927c1"): true, - // DeDust pool, e.g. https://dedust.io/pools/0:0706d6f329feb86a9876c7d1dcbb189fb99482f5794f0c746c75d204b15fccac - mustBase64Hash("c0f9d14fbc8e14f0d72cba2214165eee35836ab174130912baf9dbfa43ead562"): true, -} - -func parseJettonAssetDump(data []byte, providers map[string]Provider) map[tongo.AccountID]AssetInfo { - raw := g.MustParseJson[map[tongo.AccountID]jettonAssetDumpItem](data) - return g.MapMapValues(raw, func(item jettonAssetDumpItem) AssetInfo { - provider, ok := providers[item.Provider] - if !ok { - panic("unknown defi provider: " + item.Provider) - } - if !validAssetType(item.TokenType) { - panic("unknown defi token type: " + string(item.TokenType)) - } - return AssetInfo{ - TokenType: item.TokenType, - DefiProvider: provider, - } - }) -} - -func validAssetType(tokenType AssetType) bool { - switch tokenType { - case AssetTypeLiquidStaking, AssetTypeLiquidPool, AssetTypeYieldToken, AssetTypeLendingSupply, AssetTypeLendingBorrow: - return true - default: - return false - } -} - -func stonfiPoolAssetInfo(admin *tongo.AccountID, codeHash string) (AssetInfo, bool) { - if admin == nil { - return AssetInfo{}, false - } - if _, ok := references.StonfiWhitelistVaults[*admin]; !ok { - return AssetInfo{}, false - } - if !stonfiPoolCodeHashes[codeHash] { - return AssetInfo{}, false - } - provider, ok := jettonDefiProviders[stonfiProviderID] - if !ok { - return AssetInfo{}, false - } - return AssetInfo{ - TokenType: AssetTypeLiquidPool, - DefiProvider: provider, - }, true -} - -func dedustPoolAssetInfo(codeHash string) (AssetInfo, bool) { - if !dedustPoolCodeHashes[codeHash] { - return AssetInfo{}, false - } - provider, ok := jettonDefiProviders[dedustProviderID] - if !ok { - return AssetInfo{}, false - } - return AssetInfo{ - TokenType: AssetTypeLiquidPool, - DefiProvider: provider, - }, true -} - -func GetProvider(tag string) (Provider, bool) { - p, ok := jettonDefiProviders[tag] - return p, ok -} - -func mustBase64Hash(hexHash string) string { - b, err := hex.DecodeString(hexHash) - if err != nil { - panic(err) - } - return base64.StdEncoding.EncodeToString(b) -} - -func AssetInfos(ctx context.Context, source JettonMasterSource, logger *zap.Logger, masters []tongo.AccountID) map[tongo.AccountID]AssetInfo { - if len(masters) == 0 { - return nil - } - - result := make(map[tongo.AccountID]AssetInfo) - unresolved := make([]tongo.AccountID, 0, len(masters)) - for _, master := range masters { - if info, ok := jettonAssetDumpInfos[master]; ok { - result[master] = info - } else { - unresolved = append(unresolved, master) - } - } - if len(unresolved) == 0 { - return result - } - - masterMetas, err := source.GetJettonMastersByAddresses(ctx, unresolved) - if err != nil { - logger.Warn("failed to get jetton masters for asset info", zap.Error(err)) - return result - } - for _, master := range masterMetas { - stonfiInfo, stonfiOk := stonfiPoolAssetInfo(master.Admin, master.CodeHash) - if stonfiOk { - result[master.Address] = stonfiInfo - continue - } - dedustInfo, dedustOk := dedustPoolAssetInfo(master.CodeHash) - if dedustOk { - result[master.Address] = dedustInfo - } - } - return result -} diff --git a/pkg/defi/asset_info_test.go b/pkg/defi/asset_info_test.go deleted file mode 100644 index cbd8a6287..000000000 --- a/pkg/defi/asset_info_test.go +++ /dev/null @@ -1,85 +0,0 @@ -package defi - -import ( - "context" - "testing" - - "github.com/tonkeeper/opentonapi/pkg/core" - "github.com/tonkeeper/tongo" - "github.com/tonkeeper/tongo/ton" - "go.uber.org/zap" -) - -func TestJettonAssetInfoSTONFiLiquidPoolMaster(t *testing.T) { - master := core.JettonMaster{ - Address: tongo.MustParseAddress("EQCGScrZe1xbyWqWDvdI6mzP-GAcAWFv6ZXuaJOuSqemxku4").ID, - Admin: accountIDPtr(ton.MustParseAccountID("0:92e1411ae546892f33b2c8a89ea90390d8ff4cfbb917a643b91e73f706fdb9d1")), - CodeHash: mustBase64Hash("ec614ea4aaea3f7768606f1c1632b3374d3de096a1e7c4ba43c8009c487fee9d"), - } - - if _, ok := jettonAssetDumpInfos[master.Address]; ok { - t.Fatalf("did not expect STON.fi liquid pool in dump for master %v", master.Address.ToRaw()) - } - - stonfiInfo, ok := stonfiPoolAssetInfo(master.Admin, master.CodeHash) - if !ok { - t.Fatalf("expected STON.fi logic asset info for master %v", master.Address.ToRaw()) - } - assertSTONFiLiquidPoolAssetInfo(t, stonfiInfo) -} - -func TestJettonAssetInfoDeDustLiquidPoolMaster(t *testing.T) { - master := core.JettonMaster{ - Address: tongo.MustParseAddress("0:00576440c4a6f443af2fcef7b27a2277eb0c552e8b898190cce9c3393d17c6e5").ID, - CodeHash: mustBase64Hash("778f0d3fe6482c50888970df5e787f40f3a4ab282170c035a5920877058c99d3"), - } - - if _, ok := jettonAssetDumpInfos[master.Address]; ok { - t.Fatalf("did not expect DeDust liquid pool in dump for master %v", master.Address.ToRaw()) - } - - infos := AssetInfos(context.Background(), staticJettonMasterSource{masters: []core.JettonMaster{master}}, zap.NewNop(), []tongo.AccountID{master.Address}) - dedustInfo, ok := infos[master.Address] - if !ok { - t.Fatalf("expected DeDust logic asset info for master %v", master.Address.ToRaw()) - } - assertDeDustLiquidPoolAssetInfo(t, dedustInfo) -} - -func assertSTONFiLiquidPoolAssetInfo(t *testing.T, info AssetInfo) { - t.Helper() - if info.TokenType != AssetTypeLiquidPool { - t.Fatalf("unexpected token type: got %q", info.TokenType) - } - if info.DefiProvider.Tag != stonfiProviderID { - t.Fatalf("unexpected provider tag: got %q", info.DefiProvider.Tag) - } - if info.DefiProvider.Name != "STON.fi" { - t.Fatalf("unexpected provider name: got %q", info.DefiProvider.Name) - } -} - -func assertDeDustLiquidPoolAssetInfo(t *testing.T, info AssetInfo) { - t.Helper() - if info.TokenType != AssetTypeLiquidPool { - t.Fatalf("unexpected token type: got %q", info.TokenType) - } - if info.DefiProvider.Tag != dedustProviderID { - t.Fatalf("unexpected provider tag: got %q", info.DefiProvider.Tag) - } - if info.DefiProvider.Name != "DeDust.io" { - t.Fatalf("unexpected provider name: got %q", info.DefiProvider.Name) - } -} - -func accountIDPtr(accountID tongo.AccountID) *tongo.AccountID { - return &accountID -} - -type staticJettonMasterSource struct { - masters []core.JettonMaster -} - -func (s staticJettonMasterSource) GetJettonMastersByAddresses(_ context.Context, _ []ton.AccountID) ([]core.JettonMaster, error) { - return s.masters, nil -} diff --git a/pkg/defi/assets.go b/pkg/defi/assets.go index 9e1f8ee06..03aa71d07 100644 --- a/pkg/defi/assets.go +++ b/pkg/defi/assets.go @@ -1,18 +1,159 @@ package defi import ( - "embed" - "io/fs" - "net/http" + "context" + _ "embed" + + "github.com/tonkeeper/opentonapi/internal/g" + "github.com/tonkeeper/opentonapi/pkg/core" + "github.com/tonkeeper/opentonapi/pkg/defi/dedust" + "github.com/tonkeeper/opentonapi/pkg/defi/stonfi" + "github.com/tonkeeper/tongo" + "github.com/tonkeeper/tongo/ton" + "go.uber.org/zap" ) -//go:embed assets/* -var defiAssetsFS embed.FS +type Provider struct { + Name string `json:"name"` + Description string `json:"description"` + Link string `json:"link"` + MiniappLink string `json:"miniapp_link"` + Icon string `json:"icon"` + Card string `json:"card"` + Full string `json:"full"` + Tag string `json:"tag"` +} + +type AssetInfo struct { + TokenType AssetType + DefiProvider Provider + LiquidityPool *LiquidityPoolAssetInfo +} + +type LiquidityPoolAssetInfo struct { + Asset0 LockedAsset + Asset1 LockedAsset +} + +type jettonAssetDumpItem struct { + TokenType AssetType `json:"token_type"` + Provider string `json:"provider"` +} + +type JettonAssetInfoSource interface { + stonfi.Source + dedust.Source + + GetJettonMastersByAddresses(ctx context.Context, addresses []ton.AccountID) ([]core.JettonMaster, error) +} + +//go:embed defi_masters_mapping.json +var jettonAssetDump []byte + +//go:embed defi_providers.json +var jettonProvidersDump []byte + +var jettonAssetDumpInfos map[tongo.AccountID]AssetInfo +var jettonDefiProviders map[string]Provider +var stonfiProvider Provider +var dedustProvider Provider + +func init() { + jettonDefiProviders = g.MustParseJson[map[string]Provider](jettonProvidersDump) + jettonAssetDumpInfos = parseJettonAssetDump(jettonAssetDump, jettonDefiProviders) + stonfiProvider = g.MustGet(jettonDefiProviders, stonfi.ProviderID) + dedustProvider = g.MustGet(jettonDefiProviders, dedust.ProviderID) +} + +func parseJettonAssetDump(data []byte, providers map[string]Provider) map[tongo.AccountID]AssetInfo { + raw := g.MustParseJson[map[tongo.AccountID]jettonAssetDumpItem](data) + return g.MapMapValues(raw, func(item jettonAssetDumpItem) AssetInfo { + provider, ok := providers[item.Provider] + if !ok { + panic("unknown defi provider: " + item.Provider) + } + if !validAssetType(item.TokenType) { + panic("unknown defi token type: " + string(item.TokenType)) + } + return AssetInfo{ + TokenType: item.TokenType, + DefiProvider: provider, + } + }) +} -func AssetsHandler() http.Handler { - assets, err := fs.Sub(defiAssetsFS, "assets") +func validAssetType(tokenType AssetType) bool { + switch tokenType { + case AssetTypeLiquidStaking, AssetTypeLiquidPool, AssetTypeYieldToken, AssetTypeLendingSupply, AssetTypeLendingBorrow: + return true + default: + return false + } +} + +func GetProvider(tag string) (Provider, bool) { + p, ok := jettonDefiProviders[tag] + return p, ok +} + +func AssetInfos(ctx context.Context, source JettonAssetInfoSource, logger *zap.Logger, masters []tongo.AccountID) map[tongo.AccountID]AssetInfo { + if len(masters) == 0 { + return nil + } + + result := make(map[tongo.AccountID]AssetInfo) + unresolved := make([]tongo.AccountID, 0, len(masters)) + for _, master := range masters { + if info, ok := jettonAssetDumpInfos[master]; ok { + result[master] = info + } else { + unresolved = append(unresolved, master) + } + } + if len(unresolved) == 0 { + return result + } + + masterMetas, err := source.GetJettonMastersByAddresses(ctx, unresolved) if err != nil { - panic(err) + logger.Warn("failed to get jetton masters for asset info", zap.Error(err)) + return result + } + + stonfiInfos, remainingJettons := stonfi.PoolAssetInfos(ctx, source, logger, masterMetas) + for account, pool := range stonfiInfos { + info := AssetInfo{ + TokenType: AssetTypeLiquidPool, DefiProvider: stonfiProvider, + LiquidityPool: toPoolAssets(pool), + } + result[account] = info + } + + dedustInfos, _ := dedust.PoolAssetInfos(ctx, source, logger, remainingJettons) + for account, pool := range dedustInfos { + info := AssetInfo{ + TokenType: AssetTypeLiquidPool, DefiProvider: dedustProvider, + LiquidityPool: toPoolAssets(pool), + } + result[account] = info + } + + return result +} + +func toPoolAssets(pool struct { + Asset0 core.Currency + Asset1 core.Currency +}) *LiquidityPoolAssetInfo { + return &LiquidityPoolAssetInfo{ + Asset0: currencyToLockedAsset(pool.Asset0), + Asset1: currencyToLockedAsset(pool.Asset1), + } +} + +func currencyToLockedAsset(c core.Currency) LockedAsset { + if c.Type == core.CurrencyJetton && c.Jetton != nil { + return LockedAsset{Type: LockedAssetTypeJetton, JettonMaster: c.Jetton} } - return http.StripPrefix("/v2/assets/defi/", http.FileServer(http.FS(assets))) + return LockedAsset{Type: LockedAssetTypeNative} } diff --git a/pkg/defi/dedust/dedust.go b/pkg/defi/dedust/dedust.go new file mode 100644 index 000000000..dbddb2b89 --- /dev/null +++ b/pkg/defi/dedust/dedust.go @@ -0,0 +1,55 @@ +package dedust + +import ( + "context" + + "github.com/tonkeeper/opentonapi/internal/g" + "github.com/tonkeeper/opentonapi/pkg/core" + "github.com/tonkeeper/tongo" + "go.uber.org/zap" +) + +const ProviderID = "dedust" + +type Source interface { + DedustPools(ctx context.Context, contracts []tongo.AccountID) (map[tongo.AccountID]core.DedustPool, error) +} + +type PoolAssetInfo struct { + Asset0 core.Currency + Asset1 core.Currency +} + +var poolCodeHashes = map[string]bool{ + g.MustHex2Base64("778f0d3fe6482c50888970df5e787f40f3a4ab282170c035a5920877058c99d3"): true, + g.MustHex2Base64("1275095b6da3911292406f4f4386f9e780099b854c6dee9ee2895ddce70927c1"): true, + g.MustHex2Base64("c0f9d14fbc8e14f0d72cba2214165eee35836ab174130912baf9dbfa43ead562"): true, +} + +func PoolAssetInfos(ctx context.Context, source Source, logger *zap.Logger, masterMetas []core.JettonMaster) (map[tongo.AccountID]PoolAssetInfo, []core.JettonMaster) { + infos := make(map[tongo.AccountID]PoolAssetInfo) + remaining := make([]core.JettonMaster, 0, len(masterMetas)) + poolIDs := make([]tongo.AccountID, 0, len(masterMetas)) + for _, master := range masterMetas { + if !poolCodeHashes[master.CodeHash] { + remaining = append(remaining, master) + continue + } + poolIDs = append(poolIDs, master.Address) + } + if len(poolIDs) == 0 { + return infos, remaining + } + pools, err := source.DedustPools(ctx, poolIDs) + if err != nil { + logger.Warn("failed to get DeDust pools for asset info", zap.Error(err)) + return infos, remaining + } + for poolID, pool := range pools { + infos[poolID] = PoolAssetInfo{ + Asset0: pool.Asset0, + Asset1: pool.Asset1, + } + } + return infos, remaining +} diff --git a/pkg/defi/evaa/evaa.go b/pkg/defi/evaa/evaa.go index 641590d21..634d47a40 100644 --- a/pkg/defi/evaa/evaa.go +++ b/pkg/defi/evaa/evaa.go @@ -117,21 +117,21 @@ func poolAsset( assetAddress := userAssetID return defi.Asset{ Type: assetType, - Amount: principal.String(), PoolAddress: &poolID, AssetAddress: &assetAddress, Provider: provider, - LockedAsset: lockedAsset(jettonMaster), + LockedAsset: lockedAsset(jettonMaster, *principal), }, true } -func lockedAsset(jettonMaster *ton.AccountID) defi.LockedAsset { +func lockedAsset(jettonMaster *ton.AccountID, amount big.Int) defi.LockedAsset { if jettonMaster == nil { return defi.LockedAsset{Type: defi.LockedAssetTypeNative} } return defi.LockedAsset{ Type: defi.LockedAssetTypeJetton, JettonMaster: jettonMaster, + Amount: amount, } } diff --git a/pkg/defi/handler.go b/pkg/defi/handler.go new file mode 100644 index 000000000..9e1f8ee06 --- /dev/null +++ b/pkg/defi/handler.go @@ -0,0 +1,18 @@ +package defi + +import ( + "embed" + "io/fs" + "net/http" +) + +//go:embed assets/* +var defiAssetsFS embed.FS + +func AssetsHandler() http.Handler { + assets, err := fs.Sub(defiAssetsFS, "assets") + if err != nil { + panic(err) + } + return http.StripPrefix("/v2/assets/defi/", http.FileServer(http.FS(assets))) +} diff --git a/pkg/defi/stonfi/stonfi.go b/pkg/defi/stonfi/stonfi.go new file mode 100644 index 000000000..cc838856c --- /dev/null +++ b/pkg/defi/stonfi/stonfi.go @@ -0,0 +1,89 @@ +package stonfi + +import ( + "context" + + "github.com/tonkeeper/opentonapi/internal/g" + "github.com/tonkeeper/opentonapi/pkg/core" + "github.com/tonkeeper/opentonapi/pkg/references" + "github.com/tonkeeper/tongo" + "go.uber.org/zap" +) + +const ProviderID = "stonfi" + +type Source interface { + JettonMastersForWallets(ctx context.Context, wallets []tongo.AccountID) (map[tongo.AccountID]tongo.AccountID, error) + STONfiPools(ctx context.Context, poolIDs []core.STONfiPoolID) (map[tongo.AccountID]core.STONfiPool, error) +} + +type PoolAssetInfo struct { + Asset0 core.Currency + Asset1 core.Currency +} + +var poolCodeHashVersions = map[string]core.STONfiVersion{ + g.MustHex2Base64("82566ad72b6568fe7276437d3b0c911aab65ed701c13601941b2917305e81c11"): core.STONfiPoolV1, + g.MustHex2Base64("ec614ea4aaea3f7768606f1c1632b3374d3de096a1e7c4ba43c8009c487fee9d"): core.STONfiPoolV2, + g.MustHex2Base64("f04a14c3231221056c3499965e4604417e324f8e9121d840120d803288715594"): core.STONfiPoolV2, + g.MustHex2Base64("fbc7e8fcca72c2b9c078b359ffa936f46384491b895b6577b0a6cb3f569040bc"): core.STONfiPoolV2, + g.MustHex2Base64("dac47636ae899081ebd4f47dc90ef9de98456b1000591069773f683c6d601fa9"): core.STONfiPoolV2, + g.MustHex2Base64("cf5d0b99fa704e7cf2c9d50a8ff8b8bc7ce0b8a74e414b9c279ac544e7aade05"): core.STONfiPoolV2, +} + +func isLiquidityPool(admin *tongo.AccountID, codeHash string) (core.STONfiVersion, bool) { + if admin == nil { + return "", false + } + if _, ok := references.StonfiWhitelistVaults[*admin]; !ok { + return "", false + } + version, ok := poolCodeHashVersions[codeHash] + if !ok { + return "", false + } + return version, true +} + +func PoolAssetInfos(ctx context.Context, source Source, logger *zap.Logger, masterMetas []core.JettonMaster) (map[tongo.AccountID]PoolAssetInfo, []core.JettonMaster) { + infos := make(map[tongo.AccountID]PoolAssetInfo) + remaining := make([]core.JettonMaster, 0, len(masterMetas)) + poolIDs := make([]core.STONfiPoolID, 0, len(masterMetas)) + for _, master := range masterMetas { + version, ok := isLiquidityPool(master.Admin, master.CodeHash) + if !ok { + remaining = append(remaining, master) + continue + } + poolIDs = append(poolIDs, core.STONfiPoolID{ID: master.Address, Version: version}) + } + if len(poolIDs) == 0 { + return infos, remaining + } + pools, err := source.STONfiPools(ctx, poolIDs) + if err != nil { + logger.Warn("failed to get STON.fi pools for asset info", zap.Error(err)) + return infos, remaining + } + wallets := make([]tongo.AccountID, 0, len(pools)*2) + for _, pool := range pools { + wallets = append(wallets, pool.Token0, pool.Token1) + } + masters, err := source.JettonMastersForWallets(ctx, wallets) + if err != nil { + logger.Warn("failed to get STON.fi pool jetton masters for asset info", zap.Error(err)) + return infos, remaining + } + for poolID, pool := range pools { + master0, ok0 := masters[pool.Token0] + master1, ok1 := masters[pool.Token1] + if !(ok0 && ok1) { + continue + } + infos[poolID] = PoolAssetInfo{ + Asset0: core.NewCurrencyJetton(&master0), + Asset1: core.NewCurrencyJetton(&master1), + } + } + return infos, remaining +} diff --git a/pkg/defi/asset.go b/pkg/defi/types.go similarity index 55% rename from pkg/defi/asset.go rename to pkg/defi/types.go index edacd8f73..d4bc76d4d 100644 --- a/pkg/defi/asset.go +++ b/pkg/defi/types.go @@ -1,8 +1,11 @@ package defi -import "github.com/tonkeeper/tongo/ton" +import ( + "math/big" + + "github.com/tonkeeper/tongo/ton" +) -// AssetType describes a DeFi position held by an account. type AssetType string const ( @@ -14,28 +17,27 @@ const ( AssetTypeLendingBorrow AssetType = "lending_borrow" ) -// LockedAssetType describes the underlying asset locked in a DeFi position. -type LockedAssetType string +// Asset is a single DeFi position of an account +type Asset struct { + Type AssetType + Provider Provider -const ( - LockedAssetTypeNative LockedAssetType = "native" - LockedAssetTypeJetton LockedAssetType = "jetton" -) + LockedAsset LockedAsset -// Asset is a single DeFi position of an account, independent of the API schema. -type Asset struct { - Type AssetType - Amount string PoolAddress *ton.AccountID AssetAddress *ton.AccountID - Provider Provider - LockedAsset LockedAsset } -// LockedAsset is the underlying asset of a DeFi position. For jetton assets it -// carries the master address; symbol, decimals and the rest are resolved from -// the jetton metadata. +// LockedAsset is the underlying asset of a DeFi position type LockedAsset struct { Type LockedAssetType + Amount big.Int JettonMaster *ton.AccountID } + +type LockedAssetType string + +const ( + LockedAssetTypeNative LockedAssetType = "native" + LockedAssetTypeJetton LockedAssetType = "jetton" +) diff --git a/pkg/defi/whales/whales.go b/pkg/defi/whales/whales.go index 0fdc4d56a..62249a02b 100644 --- a/pkg/defi/whales/whales.go +++ b/pkg/defi/whales/whales.go @@ -1,11 +1,9 @@ -// Package whales resolves an account's TON Whales staking positions into -// defi.Asset values, independent of the API schema. package whales import ( "context" "fmt" - "strconv" + "math/big" "github.com/tonkeeper/opentonapi/pkg/core" "github.com/tonkeeper/opentonapi/pkg/defi" @@ -14,12 +12,10 @@ import ( "go.uber.org/zap" ) -// PoolsSource provides the whales pools an account participates in. type PoolsSource interface { GetParticipatingInWhalesPools(ctx context.Context, id ton.AccountID) ([]core.Nominator, error) } -// Assets returns the TON Whales staking positions of an account. func Assets(ctx context.Context, source PoolsSource, logger *zap.Logger, accountID ton.AccountID) []defi.Asset { whalesPools, err := source.GetParticipatingInWhalesPools(ctx, accountID) if err != nil { @@ -38,9 +34,11 @@ func Assets(ctx context.Context, source PoolsSource, logger *zap.Logger, account pool := w.Pool asset := defi.Asset{ Type: defi.AssetTypeStaking, - Amount: strconv.FormatInt(w.MemberBalance, 10), PoolAddress: &pool, - LockedAsset: defi.LockedAsset{Type: defi.LockedAssetTypeNative}, + LockedAsset: defi.LockedAsset{ + Type: defi.LockedAssetTypeNative, + Amount: *big.NewInt(w.MemberBalance), + }, } if providerOk { p := provider diff --git a/pkg/litestorage/dedust.go b/pkg/litestorage/dedust.go index 65bf6e5e7..a18324ecd 100644 --- a/pkg/litestorage/dedust.go +++ b/pkg/litestorage/dedust.go @@ -18,7 +18,7 @@ func (s *LiteStorage) DedustPools(ctx context.Context, poolIDs []tongo.AccountID if result, ok := value.(abi.GetAssets_DedustResult); ok { pools[poolID] = core.DedustPool{ Asset0: DedustAssetToCurrency(result.Asset0), - Asset1: DedustAssetToCurrency(result.Asset0), + Asset1: DedustAssetToCurrency(result.Asset1), } } } diff --git a/pkg/oas/oas_json_gen.go b/pkg/oas/oas_json_gen.go index 558546900..024be324f 100644 --- a/pkg/oas/oas_json_gen.go +++ b/pkg/oas/oas_json_gen.go @@ -14077,8 +14077,8 @@ func (s *DefiAsset) Encode(e *jx.Encoder) { // encodeFields encodes fields. func (s *DefiAsset) encodeFields(e *jx.Encoder) { { - e.FieldStart("asset_type") - s.AssetType.Encode(e) + e.FieldStart("type") + s.Type.Encode(e) } { e.FieldStart("amount") @@ -14107,7 +14107,7 @@ func (s *DefiAsset) encodeFields(e *jx.Encoder) { } var jsonFieldsNameOfDefiAsset = [6]string{ - 0: "asset_type", + 0: "type", 1: "amount", 2: "pool_address", 3: "asset_address", @@ -14124,15 +14124,15 @@ func (s *DefiAsset) Decode(d *jx.Decoder) error { if err := d.ObjBytes(func(d *jx.Decoder, k []byte) error { switch string(k) { - case "asset_type": + case "type": requiredBitSet[0] |= 1 << 0 if err := func() error { - if err := s.AssetType.Decode(d); err != nil { + if err := s.Type.Decode(d); err != nil { return err } return nil }(); err != nil { - return errors.Wrap(err, "decode field \"asset_type\"") + return errors.Wrap(err, "decode field \"type\"") } case "amount": requiredBitSet[0] |= 1 << 1 @@ -14242,50 +14242,50 @@ func (s *DefiAsset) UnmarshalJSON(data []byte) error { return s.Decode(d) } -// Encode encodes DefiAssetAssetType as json. -func (s DefiAssetAssetType) Encode(e *jx.Encoder) { +// Encode encodes DefiAssetType as json. +func (s DefiAssetType) Encode(e *jx.Encoder) { e.Str(string(s)) } -// Decode decodes DefiAssetAssetType from json. -func (s *DefiAssetAssetType) Decode(d *jx.Decoder) error { +// Decode decodes DefiAssetType from json. +func (s *DefiAssetType) Decode(d *jx.Decoder) error { if s == nil { - return errors.New("invalid: unable to decode DefiAssetAssetType to nil") + return errors.New("invalid: unable to decode DefiAssetType to nil") } v, err := d.StrBytes() if err != nil { return err } // Try to use constant string. - switch DefiAssetAssetType(v) { - case DefiAssetAssetTypeStaking: - *s = DefiAssetAssetTypeStaking - case DefiAssetAssetTypeLendingSupply: - *s = DefiAssetAssetTypeLendingSupply - case DefiAssetAssetTypeLendingBorrow: - *s = DefiAssetAssetTypeLendingBorrow - case DefiAssetAssetTypeLiquidStaking: - *s = DefiAssetAssetTypeLiquidStaking - case DefiAssetAssetTypeLiquidPool: - *s = DefiAssetAssetTypeLiquidPool - case DefiAssetAssetTypeYieldToken: - *s = DefiAssetAssetTypeYieldToken + switch DefiAssetType(v) { + case DefiAssetTypeStaking: + *s = DefiAssetTypeStaking + case DefiAssetTypeLendingSupply: + *s = DefiAssetTypeLendingSupply + case DefiAssetTypeLendingBorrow: + *s = DefiAssetTypeLendingBorrow + case DefiAssetTypeLiquidStaking: + *s = DefiAssetTypeLiquidStaking + case DefiAssetTypeLiquidPool: + *s = DefiAssetTypeLiquidPool + case DefiAssetTypeYieldToken: + *s = DefiAssetTypeYieldToken default: - *s = DefiAssetAssetType(v) + *s = DefiAssetType(v) } return nil } // MarshalJSON implements stdjson.Marshaler. -func (s DefiAssetAssetType) MarshalJSON() ([]byte, error) { +func (s DefiAssetType) MarshalJSON() ([]byte, error) { e := jx.Encoder{} s.Encode(&e) return e.Bytes(), nil } // UnmarshalJSON implements stdjson.Unmarshaler. -func (s *DefiAssetAssetType) UnmarshalJSON(data []byte) error { +func (s *DefiAssetType) UnmarshalJSON(data []byte) error { d := jx.DecodeBytes(data) return s.Decode(d) } @@ -14396,6 +14396,115 @@ func (s *DefiAssets) UnmarshalJSON(data []byte) error { return s.Decode(d) } +// Encode implements json.Marshaler. +func (s *DefiLiquidPoolAssets) Encode(e *jx.Encoder) { + e.ObjStart() + s.encodeFields(e) + e.ObjEnd() +} + +// encodeFields encodes fields. +func (s *DefiLiquidPoolAssets) encodeFields(e *jx.Encoder) { + { + e.FieldStart("asset0") + s.Asset0.Encode(e) + } + { + e.FieldStart("asset1") + s.Asset1.Encode(e) + } +} + +var jsonFieldsNameOfDefiLiquidPoolAssets = [2]string{ + 0: "asset0", + 1: "asset1", +} + +// Decode decodes DefiLiquidPoolAssets from json. +func (s *DefiLiquidPoolAssets) Decode(d *jx.Decoder) error { + if s == nil { + return errors.New("invalid: unable to decode DefiLiquidPoolAssets to nil") + } + var requiredBitSet [1]uint8 + + if err := d.ObjBytes(func(d *jx.Decoder, k []byte) error { + switch string(k) { + case "asset0": + requiredBitSet[0] |= 1 << 0 + if err := func() error { + if err := s.Asset0.Decode(d); err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"asset0\"") + } + case "asset1": + requiredBitSet[0] |= 1 << 1 + if err := func() error { + if err := s.Asset1.Decode(d); err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"asset1\"") + } + default: + return d.Skip() + } + return nil + }); err != nil { + return errors.Wrap(err, "decode DefiLiquidPoolAssets") + } + // Validate required fields. + var failures []validate.FieldError + for i, mask := range [1]uint8{ + 0b00000011, + } { + if result := (requiredBitSet[i] & mask) ^ mask; result != 0 { + // Mask only required fields and check equality to mask using XOR. + // + // If XOR result is not zero, result is not equal to expected, so some fields are missed. + // Bits of fields which would be set are actually bits of missed fields. + missed := bits.OnesCount8(result) + for bitN := 0; bitN < missed; bitN++ { + bitIdx := bits.TrailingZeros8(result) + fieldIdx := i*8 + bitIdx + var name string + if fieldIdx < len(jsonFieldsNameOfDefiLiquidPoolAssets) { + name = jsonFieldsNameOfDefiLiquidPoolAssets[fieldIdx] + } else { + name = strconv.Itoa(fieldIdx) + } + failures = append(failures, validate.FieldError{ + Name: name, + Error: validate.ErrFieldRequired, + }) + // Reset bit. + result &^= 1 << bitIdx + } + } + } + if len(failures) > 0 { + return &validate.Error{Fields: failures} + } + + return nil +} + +// MarshalJSON implements stdjson.Marshaler. +func (s *DefiLiquidPoolAssets) MarshalJSON() ([]byte, error) { + e := jx.Encoder{} + s.Encode(&e) + return e.Bytes(), nil +} + +// UnmarshalJSON implements stdjson.Unmarshaler. +func (s *DefiLiquidPoolAssets) UnmarshalJSON(data []byte) error { + d := jx.DecodeBytes(data) + return s.Decode(d) +} + // Encode implements json.Marshaler. func (s *DefiLockedAsset) Encode(e *jx.Encoder) { e.ObjStart() @@ -25021,15 +25130,29 @@ func (s *JettonAssetInfo) encodeFields(e *jx.Encoder) { e.FieldStart("token_type") s.TokenType.Encode(e) } + { + if s.Type.Set { + e.FieldStart("type") + s.Type.Encode(e) + } + } { e.FieldStart("defi_provider") s.DefiProvider.Encode(e) } + { + if s.PoolAssets.Set { + e.FieldStart("pool_assets") + s.PoolAssets.Encode(e) + } + } } -var jsonFieldsNameOfJettonAssetInfo = [2]string{ +var jsonFieldsNameOfJettonAssetInfo = [4]string{ 0: "token_type", - 1: "defi_provider", + 1: "type", + 2: "defi_provider", + 3: "pool_assets", } // Decode decodes JettonAssetInfo from json. @@ -25051,8 +25174,18 @@ func (s *JettonAssetInfo) Decode(d *jx.Decoder) error { }(); err != nil { return errors.Wrap(err, "decode field \"token_type\"") } + case "type": + if err := func() error { + s.Type.Reset() + if err := s.Type.Decode(d); err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"type\"") + } case "defi_provider": - requiredBitSet[0] |= 1 << 1 + requiredBitSet[0] |= 1 << 2 if err := func() error { if err := s.DefiProvider.Decode(d); err != nil { return err @@ -25061,6 +25194,16 @@ func (s *JettonAssetInfo) Decode(d *jx.Decoder) error { }(); err != nil { return errors.Wrap(err, "decode field \"defi_provider\"") } + case "pool_assets": + if err := func() error { + s.PoolAssets.Reset() + if err := s.PoolAssets.Decode(d); err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"pool_assets\"") + } default: return d.Skip() } @@ -25071,7 +25214,7 @@ func (s *JettonAssetInfo) Decode(d *jx.Decoder) error { // Validate required fields. var failures []validate.FieldError for i, mask := range [1]uint8{ - 0b00000011, + 0b00000101, } { if result := (requiredBitSet[i] & mask) ^ mask; result != 0 { // Mask only required fields and check equality to mask using XOR. @@ -25144,6 +25287,12 @@ func (s *JettonBalance) encodeFields(e *jx.Encoder) { e.FieldStart("jetton") s.Jetton.Encode(e) } + { + if s.DefiAsset.Set { + e.FieldStart("defi_asset") + s.DefiAsset.Encode(e) + } + } { if s.Extensions != nil { e.FieldStart("extensions") @@ -25162,13 +25311,14 @@ func (s *JettonBalance) encodeFields(e *jx.Encoder) { } } -var jsonFieldsNameOfJettonBalance = [6]string{ +var jsonFieldsNameOfJettonBalance = [7]string{ 0: "balance", 1: "price", 2: "wallet_address", 3: "jetton", - 4: "extensions", - 5: "lock", + 4: "defi_asset", + 5: "extensions", + 6: "lock", } // Decode decodes JettonBalance from json. @@ -25222,6 +25372,16 @@ func (s *JettonBalance) Decode(d *jx.Decoder) error { }(); err != nil { return errors.Wrap(err, "decode field \"jetton\"") } + case "defi_asset": + if err := func() error { + s.DefiAsset.Reset() + if err := s.DefiAsset.Decode(d); err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"defi_asset\"") + } case "extensions": if err := func() error { s.Extensions = make([]string, 0) @@ -27463,26 +27623,19 @@ func (s *JettonPreview) encodeFields(e *jx.Encoder) { s.Description.Encode(e) } } - { - if s.AssetInfo.Set { - e.FieldStart("asset_info") - s.AssetInfo.Encode(e) - } - } } -var jsonFieldsNameOfJettonPreview = [11]string{ - 0: "address", - 1: "name", - 2: "symbol", - 3: "decimals", - 4: "image", - 5: "verification", - 6: "custom_payload_api_uri", - 7: "score", - 8: "scaled_ui", - 9: "description", - 10: "asset_info", +var jsonFieldsNameOfJettonPreview = [10]string{ + 0: "address", + 1: "name", + 2: "symbol", + 3: "decimals", + 4: "image", + 5: "verification", + 6: "custom_payload_api_uri", + 7: "score", + 8: "scaled_ui", + 9: "description", } // Decode decodes JettonPreview from json. @@ -27606,16 +27759,6 @@ func (s *JettonPreview) Decode(d *jx.Decoder) error { }(); err != nil { return errors.Wrap(err, "decode field \"description\"") } - case "asset_info": - if err := func() error { - s.AssetInfo.Reset() - if err := s.AssetInfo.Decode(d); err != nil { - return err - } - return nil - }(); err != nil { - return errors.Wrap(err, "decode field \"asset_info\"") - } default: return d.Skip() } @@ -34967,6 +35110,72 @@ func (s *OptDecodedMessageExtInMsgDecodedWalletV5) UnmarshalJSON(data []byte) er return s.Decode(d) } +// Encode encodes DefiAssetType as json. +func (o OptDefiAssetType) Encode(e *jx.Encoder) { + if !o.Set { + return + } + e.Str(string(o.Value)) +} + +// Decode decodes DefiAssetType from json. +func (o *OptDefiAssetType) Decode(d *jx.Decoder) error { + if o == nil { + return errors.New("invalid: unable to decode OptDefiAssetType to nil") + } + o.Set = true + if err := o.Value.Decode(d); err != nil { + return err + } + return nil +} + +// MarshalJSON implements stdjson.Marshaler. +func (s OptDefiAssetType) MarshalJSON() ([]byte, error) { + e := jx.Encoder{} + s.Encode(&e) + return e.Bytes(), nil +} + +// UnmarshalJSON implements stdjson.Unmarshaler. +func (s *OptDefiAssetType) UnmarshalJSON(data []byte) error { + d := jx.DecodeBytes(data) + return s.Decode(d) +} + +// Encode encodes DefiLiquidPoolAssets as json. +func (o OptDefiLiquidPoolAssets) Encode(e *jx.Encoder) { + if !o.Set { + return + } + o.Value.Encode(e) +} + +// Decode decodes DefiLiquidPoolAssets from json. +func (o *OptDefiLiquidPoolAssets) Decode(d *jx.Decoder) error { + if o == nil { + return errors.New("invalid: unable to decode OptDefiLiquidPoolAssets to nil") + } + o.Set = true + if err := o.Value.Decode(d); err != nil { + return err + } + return nil +} + +// MarshalJSON implements stdjson.Marshaler. +func (s OptDefiLiquidPoolAssets) MarshalJSON() ([]byte, error) { + e := jx.Encoder{} + s.Encode(&e) + return e.Bytes(), nil +} + +// UnmarshalJSON implements stdjson.Unmarshaler. +func (s *OptDefiLiquidPoolAssets) UnmarshalJSON(data []byte) error { + d := jx.DecodeBytes(data) + return s.Decode(d) +} + // Encode encodes DepositStakeAction as json. func (o OptDepositStakeAction) Encode(e *jx.Encoder) { if !o.Set { diff --git a/pkg/oas/oas_schemas_gen.go b/pkg/oas/oas_schemas_gen.go index 21ad8e4b3..8b7c1dcff 100644 --- a/pkg/oas/oas_schemas_gen.go +++ b/pkg/oas/oas_schemas_gen.go @@ -5207,7 +5207,7 @@ func (s *DecodedRawMessageMessage) SetDecodedBody(val jx.Raw) { // Ref: #/components/schemas/DefiAsset type DefiAsset struct { - AssetType DefiAssetAssetType `json:"asset_type"` + Type DefiAssetType `json:"type"` // Amount in minimal units of the locked asset. Amount string `json:"amount"` PoolAddress OptString `json:"pool_address"` @@ -5216,9 +5216,9 @@ type DefiAsset struct { LockedAsset DefiLockedAsset `json:"locked_asset"` } -// GetAssetType returns the value of AssetType. -func (s *DefiAsset) GetAssetType() DefiAssetAssetType { - return s.AssetType +// GetType returns the value of Type. +func (s *DefiAsset) GetType() DefiAssetType { + return s.Type } // GetAmount returns the value of Amount. @@ -5246,9 +5246,9 @@ func (s *DefiAsset) GetLockedAsset() DefiLockedAsset { return s.LockedAsset } -// SetAssetType sets the value of AssetType. -func (s *DefiAsset) SetAssetType(val DefiAssetAssetType) { - s.AssetType = val +// SetType sets the value of Type. +func (s *DefiAsset) SetType(val DefiAssetType) { + s.Type = val } // SetAmount sets the value of Amount. @@ -5276,44 +5276,44 @@ func (s *DefiAsset) SetLockedAsset(val DefiLockedAsset) { s.LockedAsset = val } -// Ref: #/components/schemas/DefiAssetAssetType -type DefiAssetAssetType string +// Ref: #/components/schemas/DefiAssetType +type DefiAssetType string const ( - DefiAssetAssetTypeStaking DefiAssetAssetType = "staking" - DefiAssetAssetTypeLendingSupply DefiAssetAssetType = "lending_supply" - DefiAssetAssetTypeLendingBorrow DefiAssetAssetType = "lending_borrow" - DefiAssetAssetTypeLiquidStaking DefiAssetAssetType = "liquid_staking" - DefiAssetAssetTypeLiquidPool DefiAssetAssetType = "liquid_pool" - DefiAssetAssetTypeYieldToken DefiAssetAssetType = "yield_token" + DefiAssetTypeStaking DefiAssetType = "staking" + DefiAssetTypeLendingSupply DefiAssetType = "lending_supply" + DefiAssetTypeLendingBorrow DefiAssetType = "lending_borrow" + DefiAssetTypeLiquidStaking DefiAssetType = "liquid_staking" + DefiAssetTypeLiquidPool DefiAssetType = "liquid_pool" + DefiAssetTypeYieldToken DefiAssetType = "yield_token" ) -// AllValues returns all DefiAssetAssetType values. -func (DefiAssetAssetType) AllValues() []DefiAssetAssetType { - return []DefiAssetAssetType{ - DefiAssetAssetTypeStaking, - DefiAssetAssetTypeLendingSupply, - DefiAssetAssetTypeLendingBorrow, - DefiAssetAssetTypeLiquidStaking, - DefiAssetAssetTypeLiquidPool, - DefiAssetAssetTypeYieldToken, +// AllValues returns all DefiAssetType values. +func (DefiAssetType) AllValues() []DefiAssetType { + return []DefiAssetType{ + DefiAssetTypeStaking, + DefiAssetTypeLendingSupply, + DefiAssetTypeLendingBorrow, + DefiAssetTypeLiquidStaking, + DefiAssetTypeLiquidPool, + DefiAssetTypeYieldToken, } } // MarshalText implements encoding.TextMarshaler. -func (s DefiAssetAssetType) MarshalText() ([]byte, error) { +func (s DefiAssetType) MarshalText() ([]byte, error) { switch s { - case DefiAssetAssetTypeStaking: + case DefiAssetTypeStaking: return []byte(s), nil - case DefiAssetAssetTypeLendingSupply: + case DefiAssetTypeLendingSupply: return []byte(s), nil - case DefiAssetAssetTypeLendingBorrow: + case DefiAssetTypeLendingBorrow: return []byte(s), nil - case DefiAssetAssetTypeLiquidStaking: + case DefiAssetTypeLiquidStaking: return []byte(s), nil - case DefiAssetAssetTypeLiquidPool: + case DefiAssetTypeLiquidPool: return []byte(s), nil - case DefiAssetAssetTypeYieldToken: + case DefiAssetTypeYieldToken: return []byte(s), nil default: return nil, errors.Errorf("invalid value: %q", s) @@ -5321,25 +5321,25 @@ func (s DefiAssetAssetType) MarshalText() ([]byte, error) { } // UnmarshalText implements encoding.TextUnmarshaler. -func (s *DefiAssetAssetType) UnmarshalText(data []byte) error { - switch DefiAssetAssetType(data) { - case DefiAssetAssetTypeStaking: - *s = DefiAssetAssetTypeStaking +func (s *DefiAssetType) UnmarshalText(data []byte) error { + switch DefiAssetType(data) { + case DefiAssetTypeStaking: + *s = DefiAssetTypeStaking return nil - case DefiAssetAssetTypeLendingSupply: - *s = DefiAssetAssetTypeLendingSupply + case DefiAssetTypeLendingSupply: + *s = DefiAssetTypeLendingSupply return nil - case DefiAssetAssetTypeLendingBorrow: - *s = DefiAssetAssetTypeLendingBorrow + case DefiAssetTypeLendingBorrow: + *s = DefiAssetTypeLendingBorrow return nil - case DefiAssetAssetTypeLiquidStaking: - *s = DefiAssetAssetTypeLiquidStaking + case DefiAssetTypeLiquidStaking: + *s = DefiAssetTypeLiquidStaking return nil - case DefiAssetAssetTypeLiquidPool: - *s = DefiAssetAssetTypeLiquidPool + case DefiAssetTypeLiquidPool: + *s = DefiAssetTypeLiquidPool return nil - case DefiAssetAssetTypeYieldToken: - *s = DefiAssetAssetTypeYieldToken + case DefiAssetTypeYieldToken: + *s = DefiAssetTypeYieldToken return nil default: return errors.Errorf("invalid value: %q", data) @@ -5361,6 +5361,32 @@ func (s *DefiAssets) SetAssets(val []DefiAsset) { s.Assets = val } +// Ref: #/components/schemas/DefiLiquidPoolAssets +type DefiLiquidPoolAssets struct { + Asset0 DefiLockedAsset `json:"asset0"` + Asset1 DefiLockedAsset `json:"asset1"` +} + +// GetAsset0 returns the value of Asset0. +func (s *DefiLiquidPoolAssets) GetAsset0() DefiLockedAsset { + return s.Asset0 +} + +// GetAsset1 returns the value of Asset1. +func (s *DefiLiquidPoolAssets) GetAsset1() DefiLockedAsset { + return s.Asset1 +} + +// SetAsset0 sets the value of Asset0. +func (s *DefiLiquidPoolAssets) SetAsset0(val DefiLockedAsset) { + s.Asset0 = val +} + +// SetAsset1 sets the value of Asset1. +func (s *DefiLiquidPoolAssets) SetAsset1(val DefiLockedAsset) { + s.Asset1 = val +} + // Ref: #/components/schemas/DefiLockedAsset type DefiLockedAsset struct { // Native Gram or jetton asset. @@ -8441,36 +8467,59 @@ func (s *InitStateRaw) SetFileHash(val string) { // Ref: #/components/schemas/JettonAssetInfo type JettonAssetInfo struct { - TokenType DefiAssetAssetType `json:"token_type"` - DefiProvider DefiProvider `json:"defi_provider"` + TokenType DefiAssetType `json:"token_type"` + Type OptDefiAssetType `json:"type"` + DefiProvider DefiProvider `json:"defi_provider"` + PoolAssets OptDefiLiquidPoolAssets `json:"pool_assets"` } // GetTokenType returns the value of TokenType. -func (s *JettonAssetInfo) GetTokenType() DefiAssetAssetType { +func (s *JettonAssetInfo) GetTokenType() DefiAssetType { return s.TokenType } +// GetType returns the value of Type. +func (s *JettonAssetInfo) GetType() OptDefiAssetType { + return s.Type +} + // GetDefiProvider returns the value of DefiProvider. func (s *JettonAssetInfo) GetDefiProvider() DefiProvider { return s.DefiProvider } +// GetPoolAssets returns the value of PoolAssets. +func (s *JettonAssetInfo) GetPoolAssets() OptDefiLiquidPoolAssets { + return s.PoolAssets +} + // SetTokenType sets the value of TokenType. -func (s *JettonAssetInfo) SetTokenType(val DefiAssetAssetType) { +func (s *JettonAssetInfo) SetTokenType(val DefiAssetType) { s.TokenType = val } +// SetType sets the value of Type. +func (s *JettonAssetInfo) SetType(val OptDefiAssetType) { + s.Type = val +} + // SetDefiProvider sets the value of DefiProvider. func (s *JettonAssetInfo) SetDefiProvider(val DefiProvider) { s.DefiProvider = val } +// SetPoolAssets sets the value of PoolAssets. +func (s *JettonAssetInfo) SetPoolAssets(val OptDefiLiquidPoolAssets) { + s.PoolAssets = val +} + // Ref: #/components/schemas/JettonBalance type JettonBalance struct { Balance string `json:"balance"` Price OptTokenRates `json:"price"` WalletAddress AccountAddress `json:"wallet_address"` Jetton JettonPreview `json:"jetton"` + DefiAsset OptJettonAssetInfo `json:"defi_asset"` Extensions []string `json:"extensions"` Lock OptJettonBalanceLock `json:"lock"` } @@ -8495,6 +8544,11 @@ func (s *JettonBalance) GetJetton() JettonPreview { return s.Jetton } +// GetDefiAsset returns the value of DefiAsset. +func (s *JettonBalance) GetDefiAsset() OptJettonAssetInfo { + return s.DefiAsset +} + // GetExtensions returns the value of Extensions. func (s *JettonBalance) GetExtensions() []string { return s.Extensions @@ -8525,6 +8579,11 @@ func (s *JettonBalance) SetJetton(val JettonPreview) { s.Jetton = val } +// SetDefiAsset sets the value of DefiAsset. +func (s *JettonBalance) SetDefiAsset(val OptJettonAssetInfo) { + s.DefiAsset = val +} + // SetExtensions sets the value of Extensions. func (s *JettonBalance) SetExtensions(val []string) { s.Extensions = val @@ -9381,7 +9440,6 @@ type JettonPreview struct { Score int32 `json:"score"` ScaledUI OptScaledUI `json:"scaled_ui"` Description OptString `json:"description"` - AssetInfo OptJettonAssetInfo `json:"asset_info"` } // GetAddress returns the value of Address. @@ -9434,11 +9492,6 @@ func (s *JettonPreview) GetDescription() OptString { return s.Description } -// GetAssetInfo returns the value of AssetInfo. -func (s *JettonPreview) GetAssetInfo() OptJettonAssetInfo { - return s.AssetInfo -} - // SetAddress sets the value of Address. func (s *JettonPreview) SetAddress(val string) { s.Address = val @@ -9489,11 +9542,6 @@ func (s *JettonPreview) SetDescription(val OptString) { s.Description = val } -// SetAssetInfo sets the value of AssetInfo. -func (s *JettonPreview) SetAssetInfo(val OptJettonAssetInfo) { - s.AssetInfo = val -} - // Ref: #/components/schemas/JettonQuantity type JettonQuantity struct { Quantity string `json:"quantity"` @@ -13957,6 +14005,98 @@ func (o OptDecodedMessageExtInMsgDecodedWalletV5) Or(d DecodedMessageExtInMsgDec return d } +// NewOptDefiAssetType returns new OptDefiAssetType with value set to v. +func NewOptDefiAssetType(v DefiAssetType) OptDefiAssetType { + return OptDefiAssetType{ + Value: v, + Set: true, + } +} + +// OptDefiAssetType is optional DefiAssetType. +type OptDefiAssetType struct { + Value DefiAssetType + Set bool +} + +// IsSet returns true if OptDefiAssetType was set. +func (o OptDefiAssetType) IsSet() bool { return o.Set } + +// Reset unsets value. +func (o *OptDefiAssetType) Reset() { + var v DefiAssetType + o.Value = v + o.Set = false +} + +// SetTo sets value to v. +func (o *OptDefiAssetType) SetTo(v DefiAssetType) { + o.Set = true + o.Value = v +} + +// Get returns value and boolean that denotes whether value was set. +func (o OptDefiAssetType) Get() (v DefiAssetType, ok bool) { + if !o.Set { + return v, false + } + return o.Value, true +} + +// Or returns value if set, or given parameter if does not. +func (o OptDefiAssetType) Or(d DefiAssetType) DefiAssetType { + if v, ok := o.Get(); ok { + return v + } + return d +} + +// NewOptDefiLiquidPoolAssets returns new OptDefiLiquidPoolAssets with value set to v. +func NewOptDefiLiquidPoolAssets(v DefiLiquidPoolAssets) OptDefiLiquidPoolAssets { + return OptDefiLiquidPoolAssets{ + Value: v, + Set: true, + } +} + +// OptDefiLiquidPoolAssets is optional DefiLiquidPoolAssets. +type OptDefiLiquidPoolAssets struct { + Value DefiLiquidPoolAssets + Set bool +} + +// IsSet returns true if OptDefiLiquidPoolAssets was set. +func (o OptDefiLiquidPoolAssets) IsSet() bool { return o.Set } + +// Reset unsets value. +func (o *OptDefiLiquidPoolAssets) Reset() { + var v DefiLiquidPoolAssets + o.Value = v + o.Set = false +} + +// SetTo sets value to v. +func (o *OptDefiLiquidPoolAssets) SetTo(v DefiLiquidPoolAssets) { + o.Set = true + o.Value = v +} + +// Get returns value and boolean that denotes whether value was set. +func (o OptDefiLiquidPoolAssets) Get() (v DefiLiquidPoolAssets, ok bool) { + if !o.Set { + return v, false + } + return o.Value, true +} + +// Or returns value if set, or given parameter if does not. +func (o OptDefiLiquidPoolAssets) Or(d DefiLiquidPoolAssets) DefiLiquidPoolAssets { + if v, ok := o.Get(); ok { + return v + } + return d +} + // NewOptDepositStakeAction returns new OptDepositStakeAction with value set to v. func NewOptDepositStakeAction(v DepositStakeAction) OptDepositStakeAction { return OptDepositStakeAction{ diff --git a/pkg/oas/oas_validators_gen.go b/pkg/oas/oas_validators_gen.go index 40a6e0b96..b7b1870f1 100644 --- a/pkg/oas/oas_validators_gen.go +++ b/pkg/oas/oas_validators_gen.go @@ -2372,13 +2372,13 @@ func (s *DefiAsset) Validate() error { var failures []validate.FieldError if err := func() error { - if err := s.AssetType.Validate(); err != nil { + if err := s.Type.Validate(); err != nil { return err } return nil }(); err != nil { failures = append(failures, validate.FieldError{ - Name: "asset_type", + Name: "type", Error: err, }) } @@ -2399,7 +2399,7 @@ func (s *DefiAsset) Validate() error { return nil } -func (s DefiAssetAssetType) Validate() error { +func (s DefiAssetType) Validate() error { switch s { case "staking": return nil @@ -2458,6 +2458,40 @@ func (s *DefiAssets) Validate() error { return nil } +func (s *DefiLiquidPoolAssets) Validate() error { + if s == nil { + return validate.ErrNilPointer + } + + var failures []validate.FieldError + if err := func() error { + if err := s.Asset0.Validate(); err != nil { + return err + } + return nil + }(); err != nil { + failures = append(failures, validate.FieldError{ + Name: "asset0", + Error: err, + }) + } + if err := func() error { + if err := s.Asset1.Validate(); err != nil { + return err + } + return nil + }(); err != nil { + failures = append(failures, validate.FieldError{ + Name: "asset1", + Error: err, + }) + } + if len(failures) > 0 { + return &validate.Error{Fields: failures} + } + return nil +} + func (s *DefiLockedAsset) Validate() error { if s == nil { return validate.ErrNilPointer @@ -3765,6 +3799,42 @@ func (s *JettonAssetInfo) Validate() error { Error: err, }) } + if err := func() error { + if value, ok := s.Type.Get(); ok { + if err := func() error { + if err := value.Validate(); err != nil { + return err + } + return nil + }(); err != nil { + return err + } + } + return nil + }(); err != nil { + failures = append(failures, validate.FieldError{ + Name: "type", + Error: err, + }) + } + if err := func() error { + if value, ok := s.PoolAssets.Get(); ok { + if err := func() error { + if err := value.Validate(); err != nil { + return err + } + return nil + }(); err != nil { + return err + } + } + return nil + }(); err != nil { + failures = append(failures, validate.FieldError{ + Name: "pool_assets", + Error: err, + }) + } if len(failures) > 0 { return &validate.Error{Fields: failures} } @@ -3806,6 +3876,24 @@ func (s *JettonBalance) Validate() error { Error: err, }) } + if err := func() error { + if value, ok := s.DefiAsset.Get(); ok { + if err := func() error { + if err := value.Validate(); err != nil { + return err + } + return nil + }(); err != nil { + return err + } + } + return nil + }(); err != nil { + failures = append(failures, validate.FieldError{ + Name: "defi_asset", + Error: err, + }) + } if len(failures) > 0 { return &validate.Error{Fields: failures} } @@ -4031,24 +4119,6 @@ func (s *JettonPreview) Validate() error { Error: err, }) } - if err := func() error { - if value, ok := s.AssetInfo.Get(); ok { - if err := func() error { - if err := value.Validate(); err != nil { - return err - } - return nil - }(); err != nil { - return err - } - } - return nil - }(); err != nil { - failures = append(failures, validate.FieldError{ - Name: "asset_info", - Error: err, - }) - } if len(failures) > 0 { return &validate.Error{Fields: failures} }