diff --git a/abi/generated_test.go b/abi/generated_test.go index 6827fd6c..80f70485 100644 --- a/abi/generated_test.go +++ b/abi/generated_test.go @@ -587,7 +587,7 @@ func TestWhalesNominators(t *testing.T) { if len(members.List.Keys()) == 0 { t.Fatal(len(members.List.Keys())) } - memberAddress := ton.NewAccountID(0, members.List.Keys()[2]) + memberAddress := ton.NewAccountID(0, members.List.Keys()[4]) _, v, err = GetMember(context.Background(), client, address, memberAddress.ToMsgAddress()) if err != nil { t.Fatal(err) diff --git a/tlb/messages.go b/tlb/messages.go index 38b07d6a..e345ef89 100644 --- a/tlb/messages.go +++ b/tlb/messages.go @@ -404,32 +404,30 @@ type SimpleLib struct { } // msg_import_ext$000 msg:^(Message Any) transaction:^Transaction -// // = InMsg; -// + // msg_import_ihr$010 msg:^(Message Any) transaction:^Transaction -// // ihr_fee:Grams proof_created:^Cell = InMsg; -// + // msg_import_imm$011 in_msg:^MsgEnvelope -// // transaction:^Transaction fwd_fee:Grams = InMsg; -// + // msg_import_fin$100 in_msg:^MsgEnvelope -// // transaction:^Transaction fwd_fee:Grams = InMsg; -// + // msg_import_tr$101 in_msg:^MsgEnvelope out_msg:^MsgEnvelope -// // transit_fee:Grams = InMsg; -// + // msg_discard_fin$110 in_msg:^MsgEnvelope transaction_id:uint64 -// // fwd_fee:Grams = InMsg; -// + // msg_discard_tr$111 in_msg:^MsgEnvelope transaction_id:uint64 -// // fwd_fee:Grams proof_delivered:^Cell = InMsg; + +//msg_import_deferred_fin$00100 in_msg:^MsgEnvelope +// transaction:^Transaction fwd_fee:Grams = InMsg; + +// msg_import_deferred_tr$00101 in_msg:^MsgEnvelope out_msg:^MsgEnvelope = InMsg; type InMsg struct { SumType MsgImportExt *struct { @@ -468,6 +466,15 @@ type InMsg struct { FwdFee Grams ProofDelivered boc.Cell `tlb:"^"` } `tlbSumType:"msg_discard_tr$111"` + MsgImportDeferredFin *struct { + InMsg MsgEnvelope `tlb:"^"` + TransactionId Transaction `tlb:"^"` + FwdFee Grams + } `tlbSumType:"msg_import_deferred_fin$00100"` + MsgImportDeferredTr *struct { + InMsg MsgEnvelope `tlb:"^"` + OutMsg MsgEnvelope `tlb:"^"` + } `tlbSumType:"msg_import_deferred_tr$00101"` } // import_fees$_ fees_collected:Grams @@ -510,6 +517,14 @@ type ImportFees struct { // msg_export_deq_imm$100 out_msg:^MsgEnvelope // // reimport:^InMsg = OutMsg; +// +// msg_export_new_defer$10100 out_msg:^MsgEnvelope +// +// transaction:^Transaction = OutMsg; +// +// msg_export_deferred_tr$10101 out_msg:^MsgEnvelope +// +// imported:^InMsg = OutMsg; type OutMsg struct { SumType MsgExportExt struct { @@ -547,14 +562,36 @@ type OutMsg struct { OutMsg MsgEnvelope `tlb:"^"` Reimport InMsg `tlb:"^"` } `tlbSumType:"msg_export_deq_imm$100"` + MsgExportNewDefer *struct { + OutMsg MsgEnvelope `tlb:"^"` + Transaction Transaction `tlb:"^"` + } `tlbSumType:"msg_export_new_defer$10100"` + MsgExportDeferredTr *struct { + OutMsg MsgEnvelope `tlb:"^"` + Imported InMsg `tlb:"^"` + } `tlbSumType:"msg_export_deferred_tr$10101"` +} + +// dispatch_queue:DispatchQueue out_queue_size:(Maybe uint48) = OutMsgQueueExtra; +type OutMsgQueueExtra struct { + Magic Magic `tlb:"out_msg_queue_extra#0"` + // key - sender address, aug - min created_lt + DispatchQueue HashmapAugE[Bits256, AccountDispatchQueue, uint64] + OutQueueSize Maybe[Uint48] +} + +// _ messages:(HashmapE 64 EnqueuedMsg) count:uint48 = AccountDispatchQueue; +type AccountDispatchQueue struct { + Messages HashmapE[Uint64, EnqueuedMsg] + Count Uint48 } // _ out_queue:OutMsgQueue proc_info:ProcessedInfo // ihr_pending:IhrPendingInfo = OutMsgQueueInfo; type OutMsgQueueInfo struct { - OutQueue HashmapAugE[Bits352, EnqueuedMsg, uint64] - ProcInfo HashmapE[Bits96, ProcessedUpto] - IhrPending HashmapE[Bits320, IhrPendingSince] + OutQueue HashmapAugE[Bits352, EnqueuedMsg, uint64] + ProcInfo HashmapE[Bits96, ProcessedUpto] + Extra Maybe[OutMsgQueueExtra] } // _ enqueued_lt:uint64 out_msg:^MsgEnvelope = EnqueuedMsg; @@ -566,12 +603,37 @@ type EnqueuedMsg struct { // msg_envelope#4 cur_addr:IntermediateAddress // next_addr:IntermediateAddress fwd_fee_remaining:Grams // msg:^(Message Any) = MsgEnvelope; +// +// msg_envelope_v2#5 cur_addr:IntermediateAddress +// +// next_addr:IntermediateAddress fwd_fee_remaining:Grams +// msg:^(Message Any) +// emitted_lt:(Maybe uint64) +// metadata:(Maybe MsgMetadata) = MsgEnvelope; type MsgEnvelope struct { - Magic Magic `tlb:"msg_envelope#4"` - CurrentAddress IntermediateAddress - NextAddress IntermediateAddress - FwdFeeRemaining Grams - Msg Message `tlb:"^"` + SumType SumType + V1 struct { + CurrentAddress IntermediateAddress + NextAddress IntermediateAddress + FwdFeeRemaining Grams + Msg Message `tlb:"^"` + } `tlbSumType:"msg_envelope#4"` + V2 struct { + CurrentAddress IntermediateAddress + NextAddress IntermediateAddress + FwdFeeRemaining Grams + Msg Message `tlb:"^"` + EmittedLT *uint64 `tlb:"maybe"` + Metadata *MsgMetadata `tlb:"maybe"` + } `tlbSumType:"msg_envelope_v2#5"` +} + +// msg_metadata#0 depth:uint32 initiator_addr:MsgAddressInt initiator_lt:uint64 = MsgMetadata; +type MsgMetadata struct { + Magic Magic `tlb:"msg_metadata#0"` + Depth uint32 + InitiatorAddr MsgAddress + InitiatorLT uint64 } // interm_addr_regular$0 use_dest_bits:(#<= 96) = IntermediateAddress; diff --git a/wallet/wallet.go b/wallet/wallet.go index abffd153..d2960e72 100644 --- a/wallet/wallet.go +++ b/wallet/wallet.go @@ -109,7 +109,7 @@ func newWallet(key ed25519.PublicKey, version Version, options Options) (wallet, case V4R1, V4R2: return newWalletV4(version, key, options), nil case V5Beta: - return newWalletV5(version, key, options), nil + return NewWalletV5Beta(version, key, options), nil case HighLoadV2R2: return newWalletHighloadV2(version, key, options), nil default: @@ -258,7 +258,7 @@ func (w *Wallet) SendV2(ctx context.Context, waitingConfirmation time.Duration, if err != nil { return ton.Bits256{}, fmt.Errorf("get account state failed: %v", err) } - params, err := w.intWallet.nextMessageParams(state) + params, err := w.intWallet.NextMessageParams(state) if err != nil { return ton.Bits256{}, err } diff --git a/wallet/wallet_highload_v2.go b/wallet/wallet_highload_v2.go index 3c68f790..a62b1b1c 100644 --- a/wallet/wallet_highload_v2.go +++ b/wallet/wallet_highload_v2.go @@ -71,14 +71,14 @@ func (w *walletHighloadV2) createSignedMsgBodyCell(privateKey ed25519.PrivateKey return signBodyCell(*bodyCell, privateKey) } -func (w *walletHighloadV2) nextMessageParams(state tlb.ShardAccount) (nextMsgParams, error) { +func (w *walletHighloadV2) NextMessageParams(state tlb.ShardAccount) (NextMsgParams, error) { initRequired := state.Account.Status() == tlb.AccountUninit || state.Account.Status() == tlb.AccountNone if !initRequired { - return nextMsgParams{}, nil + return NextMsgParams{}, nil } stateInit, err := w.generateStateInit() if err != nil { - return nextMsgParams{}, err + return NextMsgParams{}, err } - return nextMsgParams{Init: stateInit}, nil + return NextMsgParams{Init: stateInit}, nil } diff --git a/wallet/wallet_v1v2.go b/wallet/wallet_v1v2.go index 7f3de39d..a2d9843e 100644 --- a/wallet/wallet_v1v2.go +++ b/wallet/wallet_v1v2.go @@ -54,6 +54,6 @@ func (w *walletV1V2) createSignedMsgBodyCell(privateKey ed25519.PrivateKey, inte panic("implement me") } -func (w *walletV1V2) nextMessageParams(state tlb.ShardAccount) (nextMsgParams, error) { +func (w *walletV1V2) NextMessageParams(state tlb.ShardAccount) (NextMsgParams, error) { panic("implement me") } diff --git a/wallet/wallet_v3.go b/wallet/wallet_v3.go index e744888c..4f3ad842 100644 --- a/wallet/wallet_v3.go +++ b/wallet/wallet_v3.go @@ -69,20 +69,20 @@ func (w *walletV3) createSignedMsgBodyCell(privateKey ed25519.PrivateKey, intern return signBodyCell(*bodyCell, privateKey) } -func (w *walletV3) nextMessageParams(state tlb.ShardAccount) (nextMsgParams, error) { +func (w *walletV3) NextMessageParams(state tlb.ShardAccount) (NextMsgParams, error) { if state.Account.Status() == tlb.AccountActive { var data DataV3 cell := boc.Cell(state.Account.Account.Storage.State.AccountActive.StateInit.Data.Value.Value) if err := tlb.Unmarshal(&cell, &data); err != nil { - return nextMsgParams{}, err + return NextMsgParams{}, err } - return nextMsgParams{ + return NextMsgParams{ Seqno: data.Seqno, }, nil } init, err := w.generateStateInit() if err != nil { - return nextMsgParams{}, err + return NextMsgParams{}, err } - return nextMsgParams{Init: init}, nil + return NextMsgParams{Init: init}, nil } diff --git a/wallet/wallet_v4.go b/wallet/wallet_v4.go index 52e98790..6a8a6b1e 100644 --- a/wallet/wallet_v4.go +++ b/wallet/wallet_v4.go @@ -72,20 +72,20 @@ func (w *walletV4) createSignedMsgBodyCell(privateKey ed25519.PrivateKey, intern return signBodyCell(*bodyCell, privateKey) } -func (w *walletV4) nextMessageParams(state tlb.ShardAccount) (nextMsgParams, error) { +func (w *walletV4) NextMessageParams(state tlb.ShardAccount) (NextMsgParams, error) { if state.Account.Status() == tlb.AccountActive { var data DataV4 cell := boc.Cell(state.Account.Account.Storage.State.AccountActive.StateInit.Data.Value.Value) if err := tlb.Unmarshal(&cell, &data); err != nil { - return nextMsgParams{}, err + return NextMsgParams{}, err } - return nextMsgParams{ + return NextMsgParams{ Seqno: data.Seqno, }, nil } init, err := w.generateStateInit() if err != nil { - return nextMsgParams{}, err + return NextMsgParams{}, err } - return nextMsgParams{Init: init}, nil + return NextMsgParams{Init: init}, nil } diff --git a/wallet/wallet_v5.go b/wallet/wallet_v5.go index 1fedc63a..7d1adee4 100644 --- a/wallet/wallet_v5.go +++ b/wallet/wallet_v5.go @@ -23,7 +23,7 @@ type DataV5 struct { Extensions tlb.HashmapE[tlb.Bits256, tlb.Uint8] } -type walletV5 struct { +type walletV5Beta struct { version Version publicKey ed25519.PublicKey workchain int @@ -45,14 +45,14 @@ type MessageConfigV5 struct { MsgType V5MsgType } -var _ wallet = &walletV5{} +var _ wallet = &walletV5Beta{} -func newWalletV5(version Version, publicKey ed25519.PublicKey, opts Options) *walletV5 { +func NewWalletV5Beta(version Version, publicKey ed25519.PublicKey, opts Options) *walletV5Beta { workchain := defaultOr(opts.Workchain, 0) subWalletID := defaultOr(opts.SubWalletID, 0) networkGlobalID := defaultOr[int32](opts.NetworkGlobalID, MainnetGlobalID) - return &walletV5{ + return &walletV5Beta{ version: version, publicKey: publicKey, workchain: workchain, @@ -61,7 +61,7 @@ func newWalletV5(version Version, publicKey ed25519.PublicKey, opts Options) *wa } } -func (w *walletV5) generateAddress() (ton.AccountID, error) { +func (w *walletV5Beta) generateAddress() (ton.AccountID, error) { stateInit, err := w.generateStateInit() if err != nil { return ton.AccountID{}, fmt.Errorf("can not generate state init: %v", err) @@ -69,7 +69,7 @@ func (w *walletV5) generateAddress() (ton.AccountID, error) { return generateAddress(w.workchain, *stateInit) } -func (w *walletV5) generateStateInit() (*tlb.StateInit, error) { +func (w *walletV5Beta) generateStateInit() (*tlb.StateInit, error) { data := DataV5{ Seqno: 0, WalletID: WalletV5ID{ @@ -82,26 +82,26 @@ func (w *walletV5) generateStateInit() (*tlb.StateInit, error) { return generateStateInit(w.version, data) } -func (w *walletV5) maxMessageNumber() int { +func (w *walletV5Beta) maxMessageNumber() int { return 254 } -func (w *walletV5) nextMessageParams(state tlb.ShardAccount) (nextMsgParams, error) { +func (w *walletV5Beta) NextMessageParams(state tlb.ShardAccount) (NextMsgParams, error) { if state.Account.Status() == tlb.AccountActive { var data DataV5 cell := boc.Cell(state.Account.Account.Storage.State.AccountActive.StateInit.Data.Value.Value) if err := tlb.Unmarshal(&cell, &data); err != nil { - return nextMsgParams{}, err + return NextMsgParams{}, err } - return nextMsgParams{ + return NextMsgParams{ Seqno: uint32(data.Seqno), }, nil } init, err := w.generateStateInit() if err != nil { - return nextMsgParams{}, err + return NextMsgParams{}, err } - return nextMsgParams{Init: init}, nil + return NextMsgParams{Init: init}, nil } @@ -113,7 +113,43 @@ type extSignedMessage struct { Actions SendMessageList `tlb:"^"` } -func (w *walletV5) createSignedMsgBodyCell(privateKey ed25519.PrivateKey, internalMessages []RawMessage, msgConfig MessageConfig) (*boc.Cell, error) { +func (w *walletV5Beta) CreateMsgBodyWithoutSignature(internalMessages []RawMessage, msgConfig MessageConfig) (*boc.Cell, error) { + actions := SendMessageList{ + Actions: make([]SendMessageAction, 0, len(internalMessages)), + } + for _, msg := range internalMessages { + actions.Actions = append(actions.Actions, SendMessageAction{ + Msg: msg.Message, + Mode: msg.Mode, + }) + } + msg := extSignedMessage{ + WalletId: WalletV5ID{ + NetworkGlobalID: w.networkGlobalID, + Workchain: uint8(w.workchain), + SubWalletID: w.subWalletID, + }, + ValidUntil: uint32(msgConfig.ValidUntil.Unix()), + Seqno: msgConfig.Seqno, + Op: false, + Actions: actions, + } + bodyCell := boc.NewCell() + if err := bodyCell.WriteUint(uint64(msgConfig.V5MsgType), 32); err != nil { + return nil, err + } + if err := tlb.Marshal(bodyCell, msg); err != nil { + return nil, err + } + bytes := [64]byte{} + if err := bodyCell.WriteBytes(bytes[:]); err != nil { + return nil, err + } + return bodyCell, nil + +} + +func (w *walletV5Beta) createSignedMsgBodyCell(privateKey ed25519.PrivateKey, internalMessages []RawMessage, msgConfig MessageConfig) (*boc.Cell, error) { actions := SendMessageList{ Actions: make([]SendMessageAction, 0, len(internalMessages)), } diff --git a/wallet/wallets_common.go b/wallet/wallets_common.go index 715c598e..8f7a2de2 100644 --- a/wallet/wallets_common.go +++ b/wallet/wallets_common.go @@ -9,7 +9,7 @@ import ( "github.com/tonkeeper/tongo/ton" ) -type nextMsgParams struct { +type NextMsgParams struct { Seqno uint32 Init *tlb.StateInit } @@ -19,7 +19,7 @@ type wallet interface { generateStateInit() (*tlb.StateInit, error) maxMessageNumber() int createSignedMsgBodyCell(privateKey ed25519.PrivateKey, internalMessages []RawMessage, msgConfig MessageConfig) (*boc.Cell, error) - nextMessageParams(state tlb.ShardAccount) (nextMsgParams, error) + NextMessageParams(state tlb.ShardAccount) (NextMsgParams, error) } func defaultOr[T any](value *T, defaultValue T) T {