Skip to content

Commit

Permalink
Add TON tx scraper
Browse files Browse the repository at this point in the history
  • Loading branch information
swift1337 committed Sep 18, 2024
1 parent 28b1298 commit 7cd1c06
Show file tree
Hide file tree
Showing 4 changed files with 222 additions and 0 deletions.
54 changes: 54 additions & 0 deletions pkg/contracts/ton/gateway_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package ton

import (
"embed"
"encoding/json"
"fmt"
"testing"

"github.com/stretchr/testify/require"
"github.com/tonkeeper/tongo/boc"
"github.com/tonkeeper/tongo/tlb"
"github.com/tonkeeper/tongo/ton"
)

func TestFixtures(t *testing.T) {
// ACT
tx := getFixtureTX(t, "01")

// ASSERT
require.Equal(t, uint64(26023788000003), tx.Lt)
require.Equal(t, "cbd6e2261334d08120e2fef428ecbb4e7773606ced878d0e6da204f2b4bf42bf", tx.Hash().Hex())
}

//go:embed testdata
var fixtures embed.FS

// testdata/$name.json tx
func getFixtureTX(t *testing.T, name string) ton.Transaction {
t.Helper()

filename := fmt.Sprintf("testdata/%s.json", name)

b, err := fixtures.ReadFile(filename)
require.NoError(t, err, filename)

// bag of cells
var raw struct {
BOC string `json:"boc"`
}

require.NoError(t, json.Unmarshal(b, &raw))

cells, err := boc.DeserializeBocHex(raw.BOC)
require.NoError(t, err)
require.Len(t, cells, 1)

cell := cells[0]

var tx ton.Transaction

require.NoError(t, tx.UnmarshalTLB(cell, &tlb.Decoder{}))

return tx
}
8 changes: 8 additions & 0 deletions pkg/contracts/ton/testdata/01.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"account": "0:997d889c815aeac21c47f86ae0e38383efc3c3463067582f6263ad48c5a1485b",
"boc": "b5ee9c7201020a0100023d0003b57997d889c815aeac21c47f86ae0e38383efc3c3463067582f6263ad48c5a1485b000017ab22a3b3031b48df020aa3647a59163a25772d81991916a2bf523b771d89deec9e5be15d58000017ab20f8740366ead1e30003465b1d0080102030201e004050082723e346a6461f48fab691e87d9fd5954595eb15351fa1c536486a863d9708b79c313c7e41677dcade29f2b424cdad8712132fbd5465b37df2e1763369e2fb12da0021904222490ee6b28018646dca110080900f168012b298e33d8992beccd0765f63941613bc9483edf610f74991a4cb72d4999ca1f00265f62272056bab08711fe1ab838e0e0fbf0f0d18c19d60bd898eb5231685216d0ee6b28000608235a00002f5645476604cdd5a3c60000003280000000000000006c6d35f934b257cebf76cf01f29a0ae9bd54b022c00101df06015de004cbec44e40ad75610e23fc357071c1c1f7e1e1a31833ac17b131d6a462d0a42d800002f5645476608cdd5a3c6c007008b0000006500000000000000008012b298e33d8992beccd0765f63941613bc9483edf610f74991a4cb72d4999ca1e876046701b1b4d7e4d2c95f3afddb3c07ca682ba6f552c08b009e42d5ac3d090000000000000000007e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006fc98510184c2880c0000000000002000000000003da7f47a5d1898330bd18801617ae23a388cbaf527c312921718ef36ce9cf8c4e40901d04",
"description": "A deposit to gw contract on testnet",
"hash": "cbd6e2261334d08120e2fef428ecbb4e7773606ced878d0e6da204f2b4bf42bf",
"logicalTime": 26023788000003,
"test": false
}
29 changes: 29 additions & 0 deletions pkg/contracts/ton/testdata/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# TON transaction scraper

`scraper.go` represents a handy tool that allows to fetch transactions from TON blockchain
for further usage in test cases.

`go run pkg/contracts/ton/testdata/scraper.go <address> <lt> <hash> [--testnet]`

## Example usage

```sh
go run pkg/contracts/ton/testdata/scraper.go \
kQCZfYicgVrqwhxH-Grg44OD78PDRjBnWC9iY61IxaFIW77M \
26023788000003 \
cbd6e2261334d08120e2fef428ecbb4e7773606ced878d0e6da204f2b4bf42bf | jq
```

Returns

```json
{
"account": "0:997d889c815aeac21c47f86ae0e38383efc3c3463067582f6263ad48c5a1485b",
"boc": "b5ee9c7201020a0100023d0003b57997d889c815aeac21c47f86ae0e38383efc3c3463067582f6263ad48c5a1485b000017ab22a3b3031b48df020aa3647a59163a25772d81991916a2bf523b771d89deec9e5be15d58000017ab20f8740366ead1e30003465b1d0080102030201e004050082723e346a6461f48fab691e87d9fd5954595eb15351fa1c536486a863d9708b79c313c7e41677dcade29f2b424cdad8712132fbd5465b37df2e1763369e2fb12da0021904222490ee6b28018646dca110080900f168012b298e33d8992beccd0765f63941613bc9483edf610f74991a4cb72d4999ca1f00265f62272056bab08711fe1ab838e0e0fbf0f0d18c19d60bd898eb5231685216d0ee6b28000608235a00002f5645476604cdd5a3c60000003280000000000000006c6d35f934b257cebf76cf01f29a0ae9bd54b022c00101df06015de004cbec44e40ad75610e23fc357071c1c1f7e1e1a31833ac17b131d6a462d0a42d800002f5645476608cdd5a3c6c007008b0000006500000000000000008012b298e33d8992beccd0765f63941613bc9483edf610f74991a4cb72d4999ca1e876046701b1b4d7e4d2c95f3afddb3c07ca682ba6f552c08b009e42d5ac3d090000000000000000007e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006fc98510184c2880c0000000000002000000000003da7f47a5d1898330bd18801617ae23a388cbaf527c312921718ef36ce9cf8c4e40901d04",
"description": "todo",
"hash": "cbd6e2261334d08120e2fef428ecbb4e7773606ced878d0e6da204f2b4bf42bf",
"logicalTime": 26023788000003,
"test": false
}
```

131 changes: 131 additions & 0 deletions pkg/contracts/ton/testdata/scraper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package main

import (
"context"
"encoding/json"
"flag"
"fmt"
"log"
"strconv"

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

func main() {
var testnet bool

flag.BoolVar(&testnet, "testnet", false, "Use testnet network")
flag.Parse()

if len(flag.Args()) != 3 {
log.Fatalf("Usage: go run scrape.go <account> <lt> <hash> [--testnet]")
}

// Parse account
acc, err := ton.ParseAccountID(flag.Arg(0))
must(err, "Unable to parse account")

// Parse LT
lt, err := strconv.ParseUint(flag.Arg(1), 10, 64)
must(err, "Unable to parse logical time")

// Parse hash
var hash ton.Bits256

must(hash.FromHex(flag.Arg(2)), "Unable to parse hash")

ctx, client := context.Background(), getClient(testnet)

state, err := client.GetAccountState(ctx, acc)
must(err, "Unable to get account state")

if state.Account.Status() != tlb.AccountActive {
fail("account %s is not active", acc.ToRaw())
}

txs, err := client.GetTransactions(ctx, 1, acc, lt, hash)
must(err, "Unable to get transactions")

switch {
case len(txs) == 0:
fail("Not found")
case len(txs) > 1:
fail("invalid tx list length (got %d, want 1); lt %d, hash %s", len(txs), hash.Hex())
}

// Print the transaction
tx := txs[0]

cell, err := transactionToCell(tx)
must(err, "unable to convert tx to cell")

bocRaw, err := cell.MarshalJSON()
must(err, "unable to marshal cell to JSON")

printAny(map[string]any{
"test": testnet,
"account": acc.ToRaw(),
"description": "todo",
"logicalTime": lt,
"hash": hash.Hex(),
"boc": json.RawMessage(bocRaw),
})
}

func getClient(testnet bool) *liteapi.Client {
if testnet {
c, err := liteapi.NewClientWithDefaultTestnet()
must(err, "unable to create testnet lite client")

return c
}

c, err := liteapi.NewClientWithDefaultTestnet()
must(err, "unable to create mainnet lite client")

return c
}

func printAny(v any) {
b, err := json.MarshalIndent(v, "", " ")
must(err, "unable marshal data")

fmt.Println(string(b))
}

func transactionToCell(tx ton.Transaction) (*boc.Cell, error) {
b, err := tx.SourceBoc()
if err != nil {
return nil, err
}

cells, err := boc.DeserializeBoc(b)
if err != nil {
return nil, err
}

if len(cells) != 1 {
return nil, fmt.Errorf("invalid cell count: %d", len(cells))
}

return cells[0], nil
}

func must(err error, msg string) {
if err == nil {
return
}

if msg == "" {
log.Fatalf("Error: %s", err.Error())
}

log.Fatalf("%s; error: %s", msg, err.Error())
}

func fail(msg string, args ...any) {
must(fmt.Errorf(msg, args...), "FAIL")
}

0 comments on commit 7cd1c06

Please sign in to comment.