From 056f4259f59a96d41b4c645e1edd4f43f3c48568 Mon Sep 17 00:00:00 2001 From: Oleg Baranov Date: Sun, 23 Apr 2023 22:04:32 +0400 Subject: [PATCH] SendWaitTransaction add return block --- example/send-to-contract/main.go | 15 +++++++++--- ton/jetton/integration_test.go | 4 ++-- ton/nft/integration_test.go | 8 +++---- ton/wallet/wallet.go | 40 ++++++++++++++++---------------- 4 files changed, 38 insertions(+), 29 deletions(-) diff --git a/example/send-to-contract/main.go b/example/send-to-contract/main.go index 14723f1f..74b45bdb 100644 --- a/example/send-to-contract/main.go +++ b/example/send-to-contract/main.go @@ -53,7 +53,7 @@ func main() { if balance.NanoTON().Uint64() >= 3000000 { // create transaction body cell, depends on what contract needs, just random example here body := cell.BeginCell(). - MustStoreUInt(0x123abc55, 32). // op code + MustStoreUInt(0x123abc55, 32). // op code MustStoreUInt(rand.Uint64(), 64). // query id // payload: MustStoreAddr(address.MustParseAddr("EQAbMQzuuGiCne0R7QEj9nrXsjM7gNjeVmrlBZouyC-SCLlO")). @@ -65,7 +65,7 @@ func main() { log.Println("sending transaction and waiting for confirmation...") - tx, err := w.SendWaitTransaction(context.Background(), &wallet.Message{ + tx, block, err := w.SendWaitTransaction(context.Background(), &wallet.Message{ Mode: 1, // pay fees separately (from balance, not from amount) InternalMessage: &tlb.InternalMessage{ Bounce: true, // return amount in case of processing error @@ -79,7 +79,16 @@ func main() { return } - log.Println("transaction sent, hash:", base64.StdEncoding.EncodeToString(tx.Hash)) + log.Println("transaction sent, confirmed at block, hash:", base64.StdEncoding.EncodeToString(tx.Hash)) + + balance, err = w.GetBalance(context.Background(), block) + if err != nil { + log.Fatalln("GetBalance err:", err.Error()) + return + } + + log.Println("balance left:", balance.TON()) + return } diff --git a/ton/jetton/integration_test.go b/ton/jetton/integration_test.go index 3845c99e..e7103a40 100644 --- a/ton/jetton/integration_test.go +++ b/ton/jetton/integration_test.go @@ -117,12 +117,12 @@ func TestJettonMasterClient_Transfer(t *testing.T) { msg = wallet.SimpleMessage(tokenWallet.Address(), tlb.MustFromTON("0.05"), burnPayload) - err = w.Send(ctx, msg, true) + _, block, err := w.SendWaitTransaction(ctx, msg) if err != nil { panic(err) } - b2, err := tokenWallet.GetBalance(ctx) + b2, err := tokenWallet.GetBalanceAtBlock(ctx, block) if err != nil { t.Fatal(err) } diff --git a/ton/nft/integration_test.go b/ton/nft/integration_test.go index 37e10ea8..7a35bbb9 100644 --- a/ton/nft/integration_test.go +++ b/ton/nft/integration_test.go @@ -103,17 +103,17 @@ func Test_NftMintTransfer(t *testing.T) { fmt.Println("Transferring NFT...") transfer := wallet.SimpleMessage(nftAddr, tlb.MustFromTON("0.065"), transferData) - err = w.Send(context.Background(), transfer, true) + _, block, err = w.SendWaitTransaction(context.Background(), transfer) if err != nil { t.Fatal("Send err:", err.Error()) } - newData, err := nft.GetNFTData(ctx) + newData, err := nft.GetNFTDataAtBlock(ctx, block) if err != nil { t.Fatal("GetNFTData err:", err.Error()) } - fullContent, err := collection.GetNFTContent(ctx, collectionData.NextItemIndex, newData.Content) + fullContent, err := collection.GetNFTContentAtBlock(ctx, collectionData.NextItemIndex, newData.Content, block) if err != nil { t.Fatal("GetNFTData err:", err.Error()) } @@ -122,7 +122,7 @@ func Test_NftMintTransfer(t *testing.T) { t.Fatal("full content incorrect", fullContent.(*ContentOffchain).URI) } - roy, err := collection.RoyaltyParams(ctx) + roy, err := collection.RoyaltyParamsAtBlock(ctx, block) if err != nil { t.Fatal("RoyaltyParams err:", err.Error()) } diff --git a/ton/wallet/wallet.go b/ton/wallet/wallet.go index 63b92bf8..6e300036 100644 --- a/ton/wallet/wallet.go +++ b/ton/wallet/wallet.go @@ -258,65 +258,65 @@ func (w *Wallet) Send(ctx context.Context, message *Message, waitConfirmation .. } func (w *Wallet) SendMany(ctx context.Context, messages []*Message, waitConfirmation ...bool) error { - _, _, err := w.sendMany(ctx, messages, waitConfirmation...) + _, _, _, err := w.sendMany(ctx, messages, waitConfirmation...) return err } // SendManyGetInMsgHash returns hash of external incoming message payload. func (w *Wallet) SendManyGetInMsgHash(ctx context.Context, messages []*Message, waitConfirmation ...bool) ([]byte, error) { - _, inMsgHash, err := w.sendMany(ctx, messages, waitConfirmation...) + _, _, inMsgHash, err := w.sendMany(ctx, messages, waitConfirmation...) return inMsgHash, err } // SendManyWaitTxHash always waits for tx block confirmation and returns found tx hash in block. func (w *Wallet) SendManyWaitTxHash(ctx context.Context, messages []*Message) ([]byte, error) { - tx, _, err := w.sendMany(ctx, messages, true) + tx, _, _, err := w.sendMany(ctx, messages, true) return tx.Hash, err } // SendManyWaitTransaction always waits for tx block confirmation and returns found tx. -func (w *Wallet) SendManyWaitTransaction(ctx context.Context, messages []*Message) (*tlb.Transaction, error) { - tx, _, err := w.sendMany(ctx, messages, true) - return tx, err +func (w *Wallet) SendManyWaitTransaction(ctx context.Context, messages []*Message) (*tlb.Transaction, *ton.BlockIDExt, error) { + tx, block, _, err := w.sendMany(ctx, messages, true) + return tx, block, err } // SendWaitTransaction always waits for tx block confirmation and returns found tx. -func (w *Wallet) SendWaitTransaction(ctx context.Context, message *Message) (*tlb.Transaction, error) { +func (w *Wallet) SendWaitTransaction(ctx context.Context, message *Message) (*tlb.Transaction, *ton.BlockIDExt, error) { return w.SendManyWaitTransaction(ctx, []*Message{message}) } -func (w *Wallet) sendMany(ctx context.Context, messages []*Message, waitConfirmation ...bool) (tx *tlb.Transaction, inMsgHash []byte, err error) { - block, err := w.api.CurrentMasterchainInfo(ctx) +func (w *Wallet) sendMany(ctx context.Context, messages []*Message, waitConfirmation ...bool) (tx *tlb.Transaction, block *ton.BlockIDExt, inMsgHash []byte, err error) { + block, err = w.api.CurrentMasterchainInfo(ctx) if err != nil { - return nil, nil, fmt.Errorf("failed to get block: %w", err) + return nil, nil, nil, fmt.Errorf("failed to get block: %w", err) } acc, err := w.api.WaitForBlock(block.SeqNo).GetAccount(ctx, block, w.addr) if err != nil { - return nil, nil, fmt.Errorf("failed to get account state: %w", err) + return nil, nil, nil, fmt.Errorf("failed to get account state: %w", err) } ext, err := w.BuildMessageForMany(ctx, messages) if err != nil { - return nil, nil, err + return nil, nil, nil, err } inMsgHash = ext.Body.Hash() if err = w.api.SendExternalMessage(ctx, ext); err != nil { - return nil, nil, fmt.Errorf("failed to send message: %w", err) + return nil, nil, nil, fmt.Errorf("failed to send message: %w", err) } if len(waitConfirmation) > 0 && waitConfirmation[0] { - tx, err = w.waitConfirmation(ctx, block, acc, ext) + tx, block, err = w.waitConfirmation(ctx, block, acc, ext) if err != nil { - return nil, nil, err + return nil, nil, nil, err } } - return tx, inMsgHash, nil + return tx, block, inMsgHash, nil } -func (w *Wallet) waitConfirmation(ctx context.Context, block *ton.BlockIDExt, acc *tlb.Account, ext *tlb.ExternalMessage) (*tlb.Transaction, error) { +func (w *Wallet) waitConfirmation(ctx context.Context, block *ton.BlockIDExt, acc *tlb.Account, ext *tlb.ExternalMessage) (*tlb.Transaction, *ton.BlockIDExt, error) { if _, hasDeadline := ctx.Deadline(); !hasDeadline { // fallback timeout to not stuck forever with background context var cancel context.CancelFunc @@ -354,7 +354,7 @@ func (w *Wallet) waitConfirmation(ctx context.Context, block *ton.BlockIDExt, ac // to prevent this we will scan till we reach last seen offset. for time.Now().Before(till) { // we try to get last 5 transactions, and check if we have our new there. - txList, err := w.api.ListTransactions(ctx, w.addr, 5, lastLt, lastHash) + txList, err := w.api.WaitForBlock(block.SeqNo).ListTransactions(ctx, w.addr, 5, lastLt, lastHash) if err != nil { continue } @@ -391,7 +391,7 @@ func (w *Wallet) waitConfirmation(ctx context.Context, block *ton.BlockIDExt, ac continue } - return transaction, nil + return transaction, block, nil } } @@ -402,7 +402,7 @@ func (w *Wallet) waitConfirmation(ctx context.Context, block *ton.BlockIDExt, ac acc = accNew } - return nil, ErrTxWasNotConfirmed + return nil, nil, ErrTxWasNotConfirmed } // TransferNoBounce - can be used to transfer TON to not yet initialized contract/wallet