Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v1.9.9 #218

Merged
merged 30 commits into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
7d687bd
Fixed BlockTransactionsExt multiroot cell
xssnick Jun 21, 2024
5e5a797
rewrite cell dump to builder
Jun 22, 2024
31f57cd
micro tvm optimization
Jun 22, 2024
9cfdd5b
roll back dict
Jun 22, 2024
3a8aead
Update NFT Mint Example to V4R2
Totemancer Jun 27, 2024
8c27d78
Update NFT Collection deploy to verified contracts
Totemancer Jun 27, 2024
5adbc49
remove silly opt with hash
Jul 1, 2024
f3c0f82
remove gofmt for cell_test
Jul 1, 2024
3e3439b
remove empty space
Jul 1, 2024
fb48bfa
Refactor V5R1 to V5Beta and Prepare Support for V5 Final (WIP)
Totemancer Jul 2, 2024
e0f781d
fix double calc
Jul 3, 2024
cb32aa6
dict.go 513 prealloc and init slice
Jul 3, 2024
0fedda1
Update to Finalized V5 Contract (WIP)
Totemancer Jul 3, 2024
8ba6af6
Update name to V5R1, V5R2
Totemancer Jul 4, 2024
1c01041
Update NFT Item code
Totemancer Jul 4, 2024
d1d8590
Add comments near the wallet versions
Totemancer Jul 4, 2024
35c68eb
Merge pull request #208 from Totemancer/dev-v19
xssnick Jul 5, 2024
59bf264
revert dict toStore
Jul 5, 2024
6bbba3b
fix: bytes repeat
Jul 5, 2024
09eedeb
Merge pull request #206 from AugustineAurelius/master
xssnick Jul 5, 2024
1cbd66d
Finalized V5 Contract Integration
Totemancer Jul 5, 2024
98d6ede
Jetton accept example & address Equals func
xssnick Jul 12, 2024
4cb1aff
Updated the denominator for the NFT collection deployment example
Totemancer Jul 12, 2024
5cbfaac
Merge pull request #215 from Totemancer/dev-v19
xssnick Jul 15, 2024
59f4297
Merge pull request #210 from Totemancer/v5final
xssnick Jul 18, 2024
33351bd
Accept jetton payments example
xssnick Jul 18, 2024
c45f9d4
Wallet V5 naming refactoring
xssnick Jul 18, 2024
6bf06e4
Added nil check for out messages in find last transaction
xssnick Jul 18, 2024
5bacf22
Fixed findLastTransactionByHash out messages list scan
xssnick Jul 20, 2024
2ec0b5d
Fixed ShardDescription field type in ShardInfo
xssnick Jul 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions address/addr.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package address

import (
"bytes"
"encoding/base64"
"encoding/binary"
"encoding/hex"
Expand Down Expand Up @@ -337,3 +338,7 @@ func (a *Address) Workchain() int32 {
func (a *Address) Data() []byte {
return a.data
}

func (a *Address) Equals(b *Address) bool {
return a.workchain == b.workchain && bytes.Equal(a.data, b.data)
}
39 changes: 33 additions & 6 deletions example/accept-payments/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/xssnick/tonutils-go/liteclient"
"github.com/xssnick/tonutils-go/tlb"
"github.com/xssnick/tonutils-go/ton"
"github.com/xssnick/tonutils-go/ton/jetton"
"log"
)

Expand All @@ -26,19 +27,17 @@ func main() {
}

// initialize ton api lite connection wrapper with full proof checks
api := ton.NewAPIClient(client, ton.ProofCheckPolicySecure).WithRetry()
api := ton.NewAPIClient(client, ton.ProofCheckPolicyFast).WithRetry()
api.SetTrustedBlockFromConfig(cfg)

log.Println("fetching and checking proofs since config init block, it may take near a minute...")
master, err := api.CurrentMasterchainInfo(context.Background()) // we fetch block just to trigger chain proof check
if err != nil {
log.Fatalln("get masterchain info err: ", err.Error())
return
}
log.Println("master proof checks are completed successfully, now communication is 100% safe!")

// address on which we are accepting payments
treasuryAddress := address.MustParseAddr("EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2N")
treasuryAddress := address.MustParseAddr("EQAYqo4u7VF0fa4DPAebk4g9lBytj2VFny7pzXR0trjtXQaO")

acc, err := api.GetAccount(context.Background(), master, treasuryAddress)
if err != nil {
Expand All @@ -58,10 +57,38 @@ func main() {

log.Println("waiting for transfers...")

// USDT master contract addr, but can be any jetton
usdt := jetton.NewJettonMasterClient(api, address.MustParseAddr("EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs"))
// get our jetton wallet address
treasuryJettonWallet, err := usdt.GetJettonWalletAtBlock(context.Background(), treasuryAddress, master)
if err != nil {
log.Fatalln("get jetton wallet address err: ", err.Error())
return
}

// listen for new transactions from channel
for tx := range transactions {
// process transaction here
log.Println(tx.String())
// only internal messages can increase the balance
if tx.IO.In != nil && tx.IO.In.MsgType == tlb.MsgTypeInternal {
ti := tx.IO.In.AsInternal()
src := ti.SrcAddr

// verify that event sender is our jetton wallet
if ti.SrcAddr.Equals(treasuryJettonWallet.Address()) {
var transfer jetton.TransferNotification
if err = tlb.LoadFromCell(&transfer, ti.Body.BeginParse()); err == nil {
// convert decimals to 6 for USDT (it can be fetched from jetton details too), default is 9
amt := tlb.MustFromNano(transfer.Amount.Nano(), 6)

// reassign sender to real jetton sender instead of its jetton wallet contract
src = transfer.Sender
log.Println("received", amt.String(), "USDT from", src.String())
}
}

// show received ton amount
log.Println("received", ti.Amount.String(), "TON from", src.String())
}

// update last processed lt and save it in db
lastProcessedLT = tx.LT
Expand Down
12 changes: 6 additions & 6 deletions example/deploy-nft-collection/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,15 @@ func main() {

func getWallet(api ton.APIClientWrapped) *wallet.Wallet {
words := strings.Split("birth pattern then forest walnut then phrase walnut fan pumpkin pattern then cluster blossom verify then forest velvet pond fiction pattern collect then then", " ")
w, err := wallet.FromSeed(api, words, wallet.V3)
w, err := wallet.FromSeed(api, words, wallet.V4R2)
if err != nil {
panic(err)
}
return w
}

func getNFTCollectionCode() *cell.Cell {
var hexBOC = "b5ee9c72410213010001fe000114ff00f4a413f4bcf2c80b0102016204020201200e030025bc82df6a2687d20699fea6a6a182de86a182c40202cd0a050201200706003d45af0047021f005778018c8cb0558cf165004fa0213cb6b12ccccc971fb0080201200908001b3e401d3232c084b281f2fff27420002d007232cffe0a33c5b25c083232c044fd003d0032c0326003ebd10638048adf000e8698180b8d848adf07d201800e98fe99ff6a2687d20699fea6a6a184108349e9ca829405d47141baf8280e8410854658056b84008646582a802e78b127d010a65b509e58fe59f80e78b64c0207d80701b28b9e382f970c892e000f18112e001718119026001f1812f82c207f97840d0c0b002801fa40304144c85005cf1613cb3fccccccc9ed5400a6357003d4308e378040f4966fa5208e2906a4208100fabe93f2c18fde81019321a05325bbf2f402fa00d43022544b30f00623ba9302a402de04926c21e2b3e6303250444313c85005cf1613cb3fccccccc9ed5400603502d33f5313bbf2e1925313ba01fa00d43028103459f0068e1201a44343c85005cf1613cb3fccccccc9ed54925f05e2020120120f0201201110002db4f47da89a1f481a67fa9a9a86028be09e008e003e00b0002fb5dafda89a1f481a67fa9a9a860d883a1a61fa61ff4806100043b8b5d31ed44d0fa40d33fd4d4d43010245f04d0d431d430d071c8cb0701cf16ccc98f34ea10e"
var hexBOC = "b5ee9c724102140100021f000114ff00f4a413f4bcf2c80b0102016202030202cd04050201200e0f04e7d10638048adf000e8698180b8d848adf07d201800e98fe99ff6a2687d20699fea6a6a184108349e9ca829405d47141baf8280e8410854658056b84008646582a802e78b127d010a65b509e58fe59f80e78b64c0207d80701b28b9e382f970c892e000f18112e001718112e001f181181981e0024060708090201200a0b00603502d33f5313bbf2e1925313ba01fa00d43028103459f0068e1201a44343c85005cf1613cb3fccccccc9ed54925f05e200a6357003d4308e378040f4966fa5208e2906a4208100fabe93f2c18fde81019321a05325bbf2f402fa00d43022544b30f00623ba9302a402de04926c21e2b3e6303250444313c85005cf1613cb3fccccccc9ed54002c323401fa40304144c85005cf1613cb3fccccccc9ed54003c8e15d4d43010344130c85005cf1613cb3fccccccc9ed54e05f04840ff2f00201200c0d003d45af0047021f005778018c8cb0558cf165004fa0213cb6b12ccccc971fb008002d007232cffe0a33c5b25c083232c044fd003d0032c03260001b3e401d3232c084b281f2fff2742002012010110025bc82df6a2687d20699fea6a6a182de86a182c40043b8b5d31ed44d0fa40d33fd4d4d43010245f04d0d431d430d071c8cb0701cf16ccc980201201213002fb5dafda89a1f481a67fa9a9a860d883a1a61fa61ff480610002db4f47da89a1f481a67fa9a9a86028be09e008e003e00b01a500c6e"
codeCellBytes, _ := hex.DecodeString(hexBOC)

codeCell, err := cell.FromBOC(codeCellBytes)
Expand All @@ -65,7 +65,7 @@ func getNFTCollectionCode() *cell.Cell {
}

func getNFTItemCode() *cell.Cell {
var hexBOC = "b5ee9c7241020d010001d0000114ff00f4a413f4bcf2c80b0102016203020009a11f9fe0050202ce050402012008060201200907001d00f232cfd633c58073c5b3327b552000113e910c1c2ebcb85360003b3b513434cffe900835d27080269fc07e90350c04090408f80c1c165b5b6002d70c8871c02497c0f83434c0c05c6c2497c0f83e903e900c7e800c5c75c87e800c7e800c3c00812ce3850c1b088d148cb1c17cb865407e90350c0408fc00f801b4c7f4cfe08417f30f45148c2ea3a1cc840dd78c9004f80c0d0d0d4d60840bf2c9a884aeb8c097c12103fcbc200b0a00727082108b77173505c8cbff5004cf1610248040708010c8cb055007cf165005fa0215cb6a12cb1fcb3f226eb39458cf17019132e201c901fb0001f65135c705f2e191fa4021f001fa40d20031fa00820afaf0801ba121945315a0a1de22d70b01c300209206a19136e220c2fff2e192218e3e821005138d91c85009cf16500bcf16712449145446a0708010c8cb055007cf165005fa0215cb6a12cb1fcb3f226eb39458cf17019132e201c901fb00104794102a375be20c0082028e3526f0018210d53276db103744006d71708010c8cb055007cf165005fa0215cb6a12cb1fcb3f226eb39458cf17019132e201c901fb0093303234e25502f003cc82807e"
var hexBOC = "b5ee9c7241020d010001d0000114ff00f4a413f4bcf2c80b0102016202030202ce04050009a11f9fe00502012006070201200b0c02d70c8871c02497c0f83434c0c05c6c2497c0f83e903e900c7e800c5c75c87e800c7e800c3c00812ce3850c1b088d148cb1c17cb865407e90350c0408fc00f801b4c7f4cfe08417f30f45148c2ea3a1cc840dd78c9004f80c0d0d0d4d60840bf2c9a884aeb8c097c12103fcbc20080900113e910c1c2ebcb8536001f65135c705f2e191fa4021f001fa40d20031fa00820afaf0801ba121945315a0a1de22d70b01c300209206a19136e220c2fff2e192218e3e821005138d91c85009cf16500bcf16712449145446a0708010c8cb055007cf165005fa0215cb6a12cb1fcb3f226eb39458cf17019132e201c901fb00104794102a375be20a00727082108b77173505c8cbff5004cf1610248040708010c8cb055007cf165005fa0215cb6a12cb1fcb3f226eb39458cf17019132e201c901fb000082028e3526f0018210d53276db103744006d71708010c8cb055007cf165005fa0215cb6a12cb1fcb3f226eb39458cf17019132e201c901fb0093303234e25502f003003b3b513434cffe900835d27080269fc07e90350c04090408f80c1c165b5b60001d00f232cfd633c58073c5b3327b5520bf75041b"
codeCellBytes, _ := hex.DecodeString(hexBOC)

codeCell, err := cell.FromBOC(codeCellBytes)
Expand All @@ -86,9 +86,9 @@ func getContractData(collectionOwnerAddr, royaltyAddr *address.Address) *cell.Ce
// = Storage;

royalty := cell.BeginCell().
MustStoreUInt(50, 16). // 5% royalty
MustStoreUInt(1000, 16).
MustStoreAddr(royaltyAddr).
MustStoreUInt(5, 16). // 5% royalty
MustStoreUInt(100, 16). // denominator
MustStoreAddr(royaltyAddr). // fee addr destination
EndCell()

// collection data
Expand Down
2 changes: 1 addition & 1 deletion example/nft-mint/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func main() {

func getWallet(api *ton.APIClient) *wallet.Wallet {
words := strings.Split("birth pattern then forest walnut then phrase walnut fan pumpkin pattern then cluster blossom verify then forest velvet pond fiction pattern collect then then", " ")
w, err := wallet.FromSeed(api, words, wallet.V3)
w, err := wallet.FromSeed(api, words, wallet.V4R2)
if err != nil {
panic(err)
}
Expand Down
10 changes: 7 additions & 3 deletions tlb/transaction.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package tlb

import (
"encoding/hex"
"fmt"
"math/big"
"reflect"
Expand Down Expand Up @@ -290,17 +291,20 @@ func (t *Transaction) String() string {
case TransactionDescriptionOrdinary:
}
if t.IO.In != nil {
build += fmt.Sprintf("LT: %d", t.LT)

if t.IO.In.MsgType == MsgTypeInternal {
in = t.IO.In.AsInternal().Amount.Nano()
}

if in.Cmp(big.NewInt(0)) != 0 {
intTx := t.IO.In.AsInternal()
build += fmt.Sprintf("LT: %d, In: %s TON, From %s", t.LT, FromNanoTON(in).String(), intTx.SrcAddr)
build += fmt.Sprintf(", In: %s TON, From %s", FromNanoTON(in).String(), intTx.SrcAddr)
comment := intTx.Comment()
if comment != "" {
build += ", Comment: " + comment
}
} else if t.IO.In.MsgType == MsgTypeExternalIn {
exTx := t.IO.In.AsExternalIn()
build += ", ExternalIn, hash: " + hex.EncodeToString(exTx.Body.Hash())
}
}

Expand Down
12 changes: 6 additions & 6 deletions ton/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ type ShardInfo struct {
ID *BlockIDExt `tl:"struct"`
ShardBlock *BlockIDExt `tl:"struct"`
ShardProof []*cell.Cell `tl:"cell optional 2"`
ShardDescription *cell.Cell `tl:"bytes"`
ShardDescription *cell.Cell `tl:"cell optional"`
}

type BlockTransactions struct {
Expand All @@ -194,11 +194,11 @@ type BlockTransactions struct {
}

type BlockTransactionsExt struct {
ID *BlockIDExt `tl:"struct"`
ReqCount int32 `tl:"int"`
Incomplete bool `tl:"bool"`
Transactions *cell.Cell `tl:"cell optional"`
Proof []byte `tl:"bytes"`
ID *BlockIDExt `tl:"struct"`
ReqCount int32 `tl:"int"`
Incomplete bool `tl:"bool"`
Transactions []*cell.Cell `tl:"cell optional"`
Proof []byte `tl:"bytes"`
}

type BlockData struct {
Expand Down
11 changes: 11 additions & 0 deletions ton/jetton/jetton.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package jetton

import (
"context"
"errors"
"fmt"
"math/big"

Expand All @@ -19,6 +20,8 @@ type TonApi interface {
SubscribeOnTransactions(workerCtx context.Context, addr *address.Address, lastProcessedLT uint64, channel chan<- *tlb.Transaction)
}

var ErrInvalidTransfer = errors.New("transfer is not verified")

type MintPayloadMasterMsg struct {
Opcode uint32 `tlb:"## 32"`
QueryID uint64 `tlb:"## 64"`
Expand All @@ -34,6 +37,14 @@ type MintPayload struct {
MasterMsg MintPayloadMasterMsg `tlb:"^"`
}

type TransferNotification struct {
_ tlb.Magic `tlb:"#7362d09c"`
QueryID uint64 `tlb:"## 64"`
Amount tlb.Coins `tlb:"."`
Sender *address.Address `tlb:"addr"`
ForwardPayload *cell.Cell `tlb:"either . ^"`
}

type Data struct {
TotalSupply *big.Int
Mintable bool
Expand Down
6 changes: 6 additions & 0 deletions ton/transactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,10 @@ func (c *APIClient) findLastTransactionByHash(ctx context.Context, addr *address
}

if isOut {
if transaction.IO.Out == nil {
continue
}

list, err := transaction.IO.Out.ToSlice()
if err != nil {
return nil, fmt.Errorf("cannot list out messages: %w", err)
Expand All @@ -334,6 +338,8 @@ func (c *APIClient) findLastTransactionByHash(ctx context.Context, addr *address
return transaction, nil
}
}

continue
} else {
if transaction.IO.In == nil {
continue
Expand Down
44 changes: 33 additions & 11 deletions ton/wallet/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,17 @@ func GetStateInit(pubKey ed25519.PublicKey, version VersionConfig, subWallet uin
switch ver {
case HighloadV3:
return nil, fmt.Errorf("use ConfigHighloadV3 for highload v3 spec")
case V5R1:
return nil, fmt.Errorf("use ConfigV5R1 for v5 spec")
case V5R1Beta:
return nil, fmt.Errorf("use ConfigV5R1Beta for V5 spec")
case V5R1Final:
return nil, fmt.Errorf("use ConfigV5R1Final for V5 spec")
}
case ConfigHighloadV3:
ver = HighloadV3
case ConfigV5R1:
ver = V5R1
case ConfigV5R1Beta:
ver = V5R1Beta
case ConfigV5R1Final:
ver = V5R1Final
}

code, ok := walletCode[ver]
Expand All @@ -84,18 +88,36 @@ func GetStateInit(pubKey ed25519.PublicKey, version VersionConfig, subWallet uin
MustStoreSlice(pubKey, 256).
MustStoreDict(nil). // empty dict of plugins
EndCell()
case V5R1:
config := version.(ConfigV5R1)
case V5R1Beta:
config := version.(ConfigV5R1Beta)

data = cell.BeginCell().
MustStoreUInt(0, 33). // seqno
MustStoreInt(int64(config.NetworkGlobalID), 32).
MustStoreInt(int64(config.Workchain), 8).
MustStoreUInt(0, 8). // version of v5
MustStoreUInt(uint64(subWallet), 32).
MustStoreUInt(0, 33). // seqno
MustStoreInt(int64(config.NetworkGlobalID), 32). // network id
MustStoreInt(int64(config.Workchain), 8). // workchain
MustStoreUInt(0, 8). // version of v5
MustStoreUInt(uint64(subWallet), 32). // default 0
MustStoreSlice(pubKey, 256).
MustStoreDict(nil). // empty dict of plugins
EndCell()
case V5R1Final:
config := version.(ConfigV5R1Final)

// Create WalletId instance
walletId := V5R1ID{
NetworkGlobalID: config.NetworkGlobalID, // -3 Testnet, -239 Mainnet
WorkChain: config.Workchain,
SubwalletNumber: uint16(subWallet),
WalletVersion: 0, // Wallet Version
}

data = cell.BeginCell().
MustStoreBoolBit(true). // storeUint(1, 1) - boolean flag for context type
MustStoreUInt(0, 32). // Sequence number, hardcoded as 0
MustStoreUInt(uint64(walletId.Serialized()), 32). // Serializing WalletId into 32-bit integer
MustStoreSlice(pubKey, 256). // Storing the public key
MustStoreDict(nil). // Storing an empty plugins dictionary
EndCell()
case HighloadV2R2, HighloadV2Verified:
data = cell.BeginCell().
MustStoreUInt(uint64(subWallet), 32).
Expand Down
19 changes: 16 additions & 3 deletions ton/wallet/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func Test_HighloadHeavyTransfer(t *testing.T) {
func Test_V5HeavyTransfer(t *testing.T) {
seed := strings.Split(_seed, " ")

w, err := FromSeed(api, seed, ConfigV5R1{
w, err := FromSeed(api, seed, ConfigV5R1Final{
NetworkGlobalID: MainnetGlobalID,
})
if err != nil {
Expand Down Expand Up @@ -114,7 +114,9 @@ func Test_V5HeavyTransfer(t *testing.T) {
func Test_WalletTransfer(t *testing.T) {
seed := strings.Split(_seed, " ")

for _, v := range []VersionConfig{ConfigV5R1{
for _, v := range []VersionConfig{ConfigV5R1Final{
NetworkGlobalID: TestnetGlobalID,
}, ConfigV5R1Beta{
NetworkGlobalID: TestnetGlobalID,
}, V3R2, V4R2, HighloadV2R2, V3R1, V4R1, HighloadV2Verified, ConfigHighloadV3{
MessageTTL: 120,
Expand Down Expand Up @@ -164,11 +166,22 @@ func Test_WalletTransfer(t *testing.T) {
comment := randString(150)
addr := address.MustParseAddr("EQA8aJTl0jfFnUZBJjTeUxu9OcbsoPBp9UcHE9upyY_X35kE")
if balance.Nano().Uint64() >= 3000000 {
err = w.Transfer(ctx, addr, tlb.MustFromTON("0.003"), comment, true)
tr, err := w.BuildTransfer(addr, tlb.MustFromTON("0.003"), false, comment)
if err != nil {
t.Fatal("Build transfer err:", err.Error())
return
}

tx, _, err := w.SendManyWaitTransaction(ctx, []*Message{tr})
if err != nil {
t.Fatal("Transfer err:", err.Error())
return
}

if tx.OutMsgCount == 0 {
t.Fatal("Out msg is 0:", ver)
return
}
} else {
t.Fatal("not enough balance")
return
Expand Down
Loading
Loading