From 0b42761bdfc0325d1f2e862eb0e52c6c27cd1e5f Mon Sep 17 00:00:00 2001 From: Oleg Baranov Date: Mon, 6 Mar 2023 12:12:55 +0400 Subject: [PATCH 1/2] Fixed connection and serialization error determinition for retry, consider nil int256 as 0 --- example/nft-info/main.go | 53 ++++++++++++++++++++++++---------------- liteclient/connection.go | 17 ++++++++++++- liteclient/pool.go | 3 +++ tl/loader.go | 8 ++++-- tl/loader_test.go | 4 ++- tlb/loader_test.go | 10 +++++++- 6 files changed, 69 insertions(+), 26 deletions(-) diff --git a/example/nft-info/main.go b/example/nft-info/main.go index 2a4933ff..ecef810c 100644 --- a/example/nft-info/main.go +++ b/example/nft-info/main.go @@ -30,36 +30,47 @@ func main() { panic(err) } - // get info about our nft's collection - collection := nft.NewCollectionClient(api, nftData.CollectionAddress) - collectionData, err := collection.GetCollectionData(context.Background()) - if err != nil { - panic(err) - } + var nftContent nft.ContentAny + if nftData.CollectionAddress.Type() != address.NoneAddress { + // get info about our nft's collection + collection := nft.NewCollectionClient(api, nftData.CollectionAddress) + collectionData, err := collection.GetCollectionData(context.Background()) + if err != nil { + panic(err) + } + + fmt.Println("Collection addr :", nftData.CollectionAddress.String()) + switch content := collectionData.Content.(type) { + case *nft.ContentOffchain: + fmt.Println(" content offchain :", content.URI) + case *nft.ContentOnchain: + fmt.Println(" content onchain :", content.Name) + } + fmt.Println(" owner :", collectionData.OwnerAddress.String()) + fmt.Println(" minted items num :", collectionData.NextItemIndex) + fmt.Println() - fmt.Println("Collection addr :", nftData.CollectionAddress.String()) - switch content := collectionData.Content.(type) { - case *nft.ContentOffchain: - fmt.Println(" content offchain :", content.URI) - case *nft.ContentOnchain: - fmt.Println(" content onchain :", content.Name) + // get full nft's content url using collection method that will merge base url with nft's data + nftContent, err = collection.GetNFTContent(context.Background(), nftData.Index, nftData.Content) + if err != nil { + panic(err) + } } - fmt.Println(" owner :", collectionData.OwnerAddress.String()) - fmt.Println(" minted items num :", collectionData.NextItemIndex) - fmt.Println() fmt.Println("NFT addr :", nftAddr.String()) fmt.Println(" initialized :", nftData.Initialized) fmt.Println(" owner :", nftData.OwnerAddress.String()) fmt.Println(" index :", nftData.Index) if nftData.Initialized { - // get full nft's content url using collection method that will merge base url with nft's data - nftContent, err := collection.GetNFTContent(context.Background(), nftData.Index, nftData.Content) - if err != nil { - panic(err) + switch content := nftData.Content.(type) { + case *nft.ContentOffchain: + fmt.Println(" content :", content.URI) + if nftContent != nil { + fmt.Println(" full content :", nftContent.(*nft.ContentOffchain).URI) + } + case *nft.ContentOnchain: + fmt.Println(" content name :", content.Name) } - fmt.Println(" part content :", nftData.Content.(*nft.ContentOffchain).URI) - fmt.Println(" full content :", nftContent.(*nft.ContentOffchain).URI) } else { fmt.Println(" empty content") } diff --git a/liteclient/connection.go b/liteclient/connection.go index de5fc07f..25a6dab1 100644 --- a/liteclient/connection.go +++ b/liteclient/connection.go @@ -362,6 +362,21 @@ func (n *connection) readData(sz uint32) ([]byte, error) { return result, nil } +type NetworkErr struct { + error +} + +func (e NetworkErr) Is(err error) bool { + if _, ok := err.(NetworkErr); ok { + return true + } + return false +} + +func (e NetworkErr) Unwrap() error { + return e.error +} + func (n *connection) send(data []byte) error { buf := make([]byte, 4) @@ -394,7 +409,7 @@ func (n *connection) send(data []byte) error { num, err := n.tcp.Write(buf) if err != nil { n.tcp.Close() - return err + return NetworkErr{err} } buf = buf[num:] diff --git a/liteclient/pool.go b/liteclient/pool.go index 63b8f364..8375e6d9 100644 --- a/liteclient/pool.go +++ b/liteclient/pool.go @@ -205,6 +205,9 @@ func (c *ConnectionPool) queryWithBalancer(req *ADNLRequest) (string, error) { host, err := reqNode.queryAdnl(req.QueryID, req.Data) if err != nil { + if !errors.Is(err, NetworkErr{}) { + return "", err + } nodeOffset++ continue } diff --git a/tl/loader.go b/tl/loader.go index 066701ed..c7b06a52 100644 --- a/tl/loader.go +++ b/tl/loader.go @@ -302,10 +302,14 @@ func serializeField(tags []string, value reflect.Value) (buf []byte, err error) switch value.Type().Elem().Kind() { case reflect.Uint8: if tags[0] == "int256" { - if len(value.Bytes()) != 32 { + bytes := value.Bytes() + if len(bytes) == 0 { + // consider it as 0 + bytes = make([]byte, 32) + } else if len(bytes) != 32 { return nil, fmt.Errorf("not 32 bytes for int256 value") } - buf = append(buf, value.Bytes()...) + buf = append(buf, bytes...) } else { buf = append(buf, ToBytes(value.Bytes())...) } diff --git a/tl/loader_test.go b/tl/loader_test.go index 34bbce03..3a1b2421 100644 --- a/tl/loader_test.go +++ b/tl/loader_test.go @@ -22,6 +22,7 @@ type TestTL struct { In *TestInner `tl:"struct boxed"` InX any `tl:"struct boxed [in]"` In2 []any `tl:"vector struct boxed [in]"` + KeyEmpty []byte `tl:"int256"` Data [][]byte `tl:"vector bytes"` } @@ -34,12 +35,13 @@ func TestParse(t *testing.T) { "e323006f" + "0200000000000000" + "7777777777777777777777777777777777777777777777777777777777777777" + "e323006f" + "0800000000000000" + "7177777777777777777777777777777777777777777777777777777777777777" + "02000000" + "e323006f" + "0700000000000000" + "7777777777777777777777777777777777777777777777777777777777777777" + "e323006f" + "0800000000000000" + "7777777777777777777777777777777777777777777777777777777777777777" + - "03000000" + "00000000" + "03112233" + "0411223344000000") + "0000000000000000000000000000000000000000000000000000000000000000" + "03000000" + "00000000" + "03112233" + "0411223344" + "000000") var tst TestTL _, err := Parse(&tst, data, true) if err != nil { panic(err) } + tst.KeyEmpty = nil data2, err := Serialize(tst, true) if err != nil { diff --git a/tlb/loader_test.go b/tlb/loader_test.go index 17cfd296..214093b0 100644 --- a/tlb/loader_test.go +++ b/tlb/loader_test.go @@ -9,6 +9,10 @@ import ( "github.com/xssnick/tonutils-go/tvm/cell" ) +type smallStruct struct { + Sz uint32 `tlb:"## 8"` +} + type manualLoad struct { Val string } @@ -37,6 +41,7 @@ type testInner struct { Addr *address.Address `tlb:"addr"` Manual manualLoad `tlb:"."` Dict *cell.Dictionary `tlb:"dict 256"` + StructMaybe *smallStruct `tlb:"maybe ^"` } type testTLB struct { @@ -62,13 +67,16 @@ func TestLoadFromCell(t *testing.T) { t.Fatal(err) } + mRef := cell.BeginCell().MustStoreUInt('y', 8).EndCell() + ref := cell.BeginCell().MustStoreUInt(0b1011, 4). MustStoreInt(-7172, 34). MustStoreUInt(0xCCA, 12). MustStoreCoins(700000). MustStoreUInt(5, 10). MustStoreUInt(7126382921832, 176). - MustStoreBoolBit(true).MustStoreAddr(addr).MustStoreUInt('x', 8).MustStoreDict(d) + MustStoreBoolBit(true).MustStoreAddr(addr).MustStoreUInt('x', 8).MustStoreDict(d). + MustStoreMaybeRef(mRef) a := cell.BeginCell().MustStoreUInt(0xFFAA, 16). MustStoreUInt(0xFFBF, 16).MustStoreBoolBit(true).MustStoreUInt(0xFFBFFFAA, 32).MustStoreRef(ref.EndCell()).MustStoreMaybeRef(nil). From 6d446d967174d1939710b5240f8adb382a2e0fbd Mon Sep 17 00:00:00 2001 From: Coverage Date: Mon, 6 Mar 2023 08:59:54 +0000 Subject: [PATCH 2/2] Updated coverage badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f6a8f544..e9c89ece 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Based on TON][ton-svg]][ton] -![Coverage](https://img.shields.io/badge/Coverage-73.3%25-brightgreen) +![Coverage](https://img.shields.io/badge/Coverage-73.1%25-brightgreen) Golang library for interacting with TON blockchain.