From 47fdc2453a39e7a9e786ccb42e3fa0f59e6a51e6 Mon Sep 17 00:00:00 2001 From: Victoria Erokhina Date: Tue, 29 Apr 2025 12:03:58 +0000 Subject: [PATCH 1/5] test --- wallet/wallet.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wallet/wallet.go b/wallet/wallet.go index 60b9585a..f8184479 100644 --- a/wallet/wallet.go +++ b/wallet/wallet.go @@ -197,6 +197,7 @@ func (w *Wallet) RawSendV2( if err != nil { return ton.Bits256{}, fmt.Errorf("can not marshal wallet message body: %v", err) } + w.address = ton.MustParseAccountID("kQDaJW6wJyc_Fpn042zXsRJcpdkomc-J-bYucBClO3N6KWny") extMsg, err := ton.CreateExternalMessage(w.address, signedBodyCell, init, tlb.VarUInteger16{}) if err != nil { return ton.Bits256{}, fmt.Errorf("can not create external message: %v", err) @@ -214,6 +215,8 @@ func (w *Wallet) RawSendV2( if err != nil { return ton.Bits256{}, fmt.Errorf("can not serialize external message cell: %v", err) } + //fmt.Println(base64.StdEncoding.EncodeToString(payload)) + t := time.Now() _, err = w.blockchain.SendMessage(ctx, payload) // TODO: add result code check if err != nil { From fc88e42ea5c91111422976d70fb321e53ab7ea94 Mon Sep 17 00:00:00 2001 From: Victoria Erokhina Date: Wed, 30 Apr 2025 11:19:44 +0000 Subject: [PATCH 2/5] test --- wallet/messages.go | 113 +++++++++++++++++++++++++++++++++----------- wallet/models.go | 2 +- wallet/wallet_v5.go | 105 +++++++++++++++++++++++----------------- 3 files changed, 149 insertions(+), 71 deletions(-) diff --git a/wallet/messages.go b/wallet/messages.go index ad601d81..c6d2e136 100644 --- a/wallet/messages.go +++ b/wallet/messages.go @@ -61,29 +61,94 @@ type MessageV5Beta struct { // MessageV5 is a message format used by wallet v5. type MessageV5 struct { tlb.SumType - // SignedInternal is an internal message authenticated by a signature. SignedInternal *struct { - WalletId uint32 - ValidUntil uint32 - Seqno uint32 - Actions *W5Actions `tlb:"maybe^"` - ExtendedActions *W5ExtendedActions `tlb:"maybe"` - Signature tlb.Bits512 - } `tlbSumType:"#73696e74"` - // SignedExternal is an external message authenticated by a signature. + WalletId uint32 + ValidUntil uint32 + Seqno uint32 + Actions *BlumActions `tlb:"maybe^"` + Signature tlb.Bits512 + } `tlbSumType:"#73696e74"` // op::internal_signed + SignedExternal *struct { - WalletId uint32 - ValidUntil uint32 - Seqno uint32 - Actions *W5Actions `tlb:"maybe^"` - ExtendedActions *W5ExtendedActions `tlb:"maybe"` - Signature tlb.Bits512 - } `tlbSumType:"#7369676e"` - ExtensionAction *struct { - QueryID uint64 - Actions *W5Actions `tlb:"maybe^"` - ExtendedActions *W5ExtendedActions `tlb:"maybe"` - } `tlbSumType:"#6578746e"` + WalletId uint32 + ValidUntil uint32 + Seqno uint32 + Actions *BlumActions `tlb:"maybe^"` + Signature tlb.Bits512 + } `tlbSumType:"#7369676e"` // op::external_signed + + AdminMessage *struct { + WalletId uint32 + ValidUntil uint32 + Seqno uint32 + Op uint32 //update_code, mass_suspend, single_suspend + Actions *BlumActions `tlb:"maybe^"` + Signatures tlb.HashmapE[tlb.Bits256, tlb.Bits512] + } `tlbSumType:"#5f1dc312"` // op::external_admin + + SessionKeyMessage *struct { + PublicKey tlb.Bits256 + Address tlb.MsgAddress + Commission tlb.Coins + Actions *BlumActions `tlb:"maybe^"` + } `tlbSumType:"#9083118"` // op::internal_execute_with_session_key +} + +type BlumActions []BlumSendMessageAction + +type BlumSendMessageAction struct { + Magic tlb.Magic `tlb:"#0ec3c86d"` // action_send_msg + Mode uint8 + Msg *boc.Cell `tlb:"^"` +} + +func (l BlumActions) MarshalTLB(c *boc.Cell, encoder *tlb.Encoder) error { + if len(l) == 0 { + return nil + } + if err := c.WriteUint(0x0ec3c86d, 32); err != nil { + return err + } + action := l[0] + if err := c.WriteUint(uint64(action.Mode), 8); err != nil { + return err + } + cell := boc.NewCell() + next := l[1:] + if err := encoder.Marshal(cell, next); err != nil { + return err + } + if err := c.AddRef(cell); err != nil { + return err + } + if err := c.AddRef(action.Msg); err != nil { + return err + } + return nil +} + +func (l *BlumActions) UnmarshalTLB(c *boc.Cell, decoder *tlb.Decoder) error { + var actions []BlumSendMessageAction + for { + switch c.BitsAvailableForRead() { + case 0: + *l = actions + return nil + case 40: + next, err := c.NextRef() + if err != nil { + return err + } + var action BlumSendMessageAction + if err := decoder.Unmarshal(c, &action); err != nil { + return err + } + actions = append(actions, action) + c = next + default: + return fmt.Errorf("unexpected bits available: %v", c.BitsAvailableForRead()) + } + } } type HighloadV2Message struct { @@ -262,12 +327,6 @@ func VerifySignature(ver Version, msg *boc.Cell, publicKey ed25519.PublicKey) er return err } return signedMsgBody.Verify(publicKey) - case V5R1: - var m tlb.Message - if err := tlb.Unmarshal(msg, &m); err != nil { - return err - } - return MessageV5VerifySignature(boc.Cell(m.Body.Value), publicKey) default: return fmt.Errorf("wallet version is not supported: %v", ver) } diff --git a/wallet/models.go b/wallet/models.go index dc932725..f614eef4 100644 --- a/wallet/models.go +++ b/wallet/models.go @@ -79,7 +79,7 @@ var codes = map[Version]string{ V4R1: "te6cckECFQEAAvUAART/APSkE/S88sgLAQIBIAIDAgFIBAUE+PKDCNcYINMf0x/THwL4I7vyY+1E0NMf0x/T//QE0VFDuvKhUVG68qIF+QFUEGT5EPKj+AAkpMjLH1JAyx9SMMv/UhD0AMntVPgPAdMHIcAAn2xRkyDXSpbTB9QC+wDoMOAhwAHjACHAAuMAAcADkTDjDQOkyMsfEssfy/8REhMUA+7QAdDTAwFxsJFb4CHXScEgkVvgAdMfIYIQcGx1Z70ighBibG5jvbAighBkc3RyvbCSXwPgAvpAMCD6RAHIygfL/8nQ7UTQgQFA1yH0BDBcgQEI9ApvoTGzkl8F4ATTP8glghBwbHVnupEx4w0kghBibG5juuMABAYHCAIBIAkKAFAB+gD0BDCCEHBsdWeDHrFwgBhQBcsFJ88WUAP6AvQAEstpyx9SEMs/AFL4J28ighBibG5jgx6xcIAYUAXLBSfPFiT6AhTLahPLH1Iwyz8B+gL0AACSghBkc3Ryuo41BIEBCPRZMO1E0IEBQNcgyAHPFvQAye1UghBkc3Rygx6xcIAYUATLBVjPFiL6AhLLassfyz+UEDRfBOLJgED7AAIBIAsMAFm9JCtvaiaECAoGuQ+gIYRw1AgIR6STfSmRDOaQPp/5g3gSgBt4EBSJhxWfMYQCAVgNDgARuMl+1E0NcLH4AD2ynftRNCBAUDXIfQEMALIygfL/8nQAYEBCPQKb6ExgAgEgDxAAGa3OdqJoQCBrkOuF/8AAGa8d9qJoQBBrkOuFj8AAbtIH+gDU1CL5AAXIygcVy//J0Hd0gBjIywXLAiLPFlAF+gIUy2sSzMzJcfsAyEAUgQEI9FHypwIAbIEBCNcYyFQgJYEBCPRR8qeCEG5vdGVwdIAYyMsFywJQBM8WghAF9eEA+gITy2oSyx/JcfsAAgBygQEI1xgwUgKBAQj0WfKn+CWCEGRzdHJwdIAYyMsFywJQBc8WghAF9eEA+gIUy2oTyx8Syz/Jc/sAAAr0AMntVEap808=", V4R2: "te6cckECFAEAAtQAART/APSkE/S88sgLAQIBIAIDAgFIBAUE+PKDCNcYINMf0x/THwL4I7vyZO1E0NMf0x/T//QE0VFDuvKhUVG68qIF+QFUEGT5EPKj+AAkpMjLH1JAyx9SMMv/UhD0AMntVPgPAdMHIcAAn2xRkyDXSpbTB9QC+wDoMOAhwAHjACHAAuMAAcADkTDjDQOkyMsfEssfy/8QERITAubQAdDTAyFxsJJfBOAi10nBIJJfBOAC0x8hghBwbHVnvSKCEGRzdHK9sJJfBeAD+kAwIPpEAcjKB8v/ydDtRNCBAUDXIfQEMFyBAQj0Cm+hMbOSXwfgBdM/yCWCEHBsdWe6kjgw4w0DghBkc3RyupJfBuMNBgcCASAICQB4AfoA9AQw+CdvIjBQCqEhvvLgUIIQcGx1Z4MesXCAGFAEywUmzxZY+gIZ9ADLaRfLH1Jgyz8gyYBA+wAGAIpQBIEBCPRZMO1E0IEBQNcgyAHPFvQAye1UAXKwjiOCEGRzdHKDHrFwgBhQBcsFUAPPFiP6AhPLassfyz/JgED7AJJfA+ICASAKCwBZvSQrb2omhAgKBrkPoCGEcNQICEekk30pkQzmkD6f+YN4EoAbeBAUiYcVnzGEAgFYDA0AEbjJftRNDXCx+AA9sp37UTQgQFA1yH0BDACyMoHy//J0AGBAQj0Cm+hMYAIBIA4PABmtznaiaEAga5Drhf/AABmvHfaiaEAQa5DrhY/AAG7SB/oA1NQi+QAFyMoHFcv/ydB3dIAYyMsFywIizxZQBfoCFMtrEszMyXP7AMhAFIEBCPRR8qcCAHCBAQjXGPoA0z/IVCBHgQEI9FHyp4IQbm90ZXB0gBjIywXLAlAGzxZQBPoCFMtqEssfyz/Jc/sAAgBsgQEI1xj6ANM/MFIkgQEI9Fnyp4IQZHN0cnB0gBjIywXLAlAFzxZQA/oCE8tqyx8Syz/Jc/sAAAr0AMntVGliJeU=", V5Beta: "te6ccgEBAQEAIwAIQgLkzzsvTG1qYeoPK1RH0mZ4WyavNjfbLe7mvNGqgm80Eg==", - V5R1: "te6cckECFAEAAoEAART/APSkE/S88sgLAQIBIAINAgFIAwQC3NAg10nBIJFbj2Mg1wsfIIIQZXh0br0hghBzaW50vbCSXwPgghBleHRuuo60gCDXIQHQdNch+kAw+kT4KPpEMFi9kVvg7UTQgQFB1yH0BYMH9A5voTGRMOGAQNchcH/bPOAxINdJgQKAuZEw4HDiEA8CASAFDAIBIAYJAgFuBwgAGa3OdqJoQCDrkOuF/8AAGa8d9qJoQBDrkOuFj8ACAUgKCwAXsyX7UTQcdch1wsfgABGyYvtRNDXCgCAAGb5fD2omhAgKDrkPoCwBAvIOAR4g1wsfghBzaWduuvLgin8PAeaO8O2i7fshgwjXIgKDCNcjIIAg1yHTH9Mf0x/tRNDSANMfINMf0//XCgAK+QFAzPkQmiiUXwrbMeHywIffArNQB7Dy0IRRJbry4IVQNrry4Ib4I7vy0IgikvgA3gGkf8jKAMsfAc8Wye1UIJL4D95w2zzYEAP27aLt+wL0BCFukmwhjkwCIdc5MHCUIccAs44tAdcoIHYeQ2wg10nACPLgkyDXSsAC8uCTINcdBscSwgBSMLDy0InXTNc5MAGk6GwShAe78uCT10rAAPLgk+1V4tIAAcAAkVvg69csCBQgkXCWAdcsCBwS4lIQseMPINdKERITAJYB+kAB+kT4KPpEMFi68uCR7UTQgQFB1xj0BQSdf8jKAEAEgwf0U/Lgi44UA4MH9Fvy4Iwi1woAIW4Bs7Dy0JDiyFADzxYS9ADJ7VQAcjDXLAgkji0h8uCS0gDtRNDSAFETuvLQj1RQMJExnAGBAUDXIdcKAPLgjuLIygBYzxbJ7VST8sCN4gAQk1vbMeHXTNC01sNe", + V5R1: "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", HighLoadV1R1: "te6ccgEBBgEAhgABFP8A9KQT9KDyyAsBAgEgAgMCAUgEBQC88oMI1xgg0x/TH9Mf+CMTu/Jj7UTQ0x/TH9P/0VEyuvKhUUS68qIE+QFUEFX5EPKj9ATR+AB/jhghgBD0eG+hb6EgmALTB9QwAfsAkTLiAbPmWwGkyMsfyx/L/8ntVAAE0DAAEaCZL9qJoa4WPw==", HighLoadV1R2: "te6ccgEBCAEAmQABFP8A9KQT9LzyyAsBAgEgAgMCAUgEBQC88oMI1xgg0x/TH9Mf+CMTu/Jj7UTQ0x/TH9P/0VEyuvKhUUS68qIE+QFUEFX5EPKj9ATR+AB/jhghgBD0eG+hb6EgmALTB9QwAfsAkTLiAbPmWwGkyMsfyx/L/8ntVAAE0DACAUgGBwAXuznO1E0NM/MdcL/4ABG4yX7UTQ1wsfg=", HighLoadV2: "te6ccgEBCQEA5QABFP8A9KQT9LzyyAsBAgEgAgcCAUgDBAAE0DACASAFBgAXvZznaiaGmvmOuF/8AEG+X5dqJoaY+Y6Z/p/5j6AmipEEAgegc30JjJLb/JXdHxQB6vKDCNcYINMf0z/4I6ofUyC58mPtRNDTH9M/0//0BNFTYIBA9A5voTHyYFFzuvKiB/kBVBCH+RDyowL0BNH4AH+OFiGAEPR4b6UgmALTB9QwAfsAkTLiAbPmW4MlochANIBA9EOK5jEByMsfE8s/y//0AMntVAgANCCAQPSWb6VsEiCUMFMDud4gkzM2AZJsIeKz", diff --git a/wallet/wallet_v5.go b/wallet/wallet_v5.go index f7e2d4f8..24ea3cd7 100644 --- a/wallet/wallet_v5.go +++ b/wallet/wallet_v5.go @@ -67,12 +67,52 @@ func (w *walletV5R1) generateAddress() (ton.AccountID, error) { return generateAddress(w.workchain, *stateInit) } +type BlumWalletData struct { + Version uint16 + Seqno uint32 + WalletID uint32 + PublicKey tlb.Bits256 + IsFrozen bool + MinSigAmount uint8 + AdminKeys tlb.HashmapE[tlb.Bits256, bool] + SingleSuspendSeqno uint32 + MassSuspendSeqno uint16 +} + func (w *walletV5R1) generateStateInit() (*tlb.StateInit, error) { - data := DataV5R1{ - IsSignatureAllowed: w.isSignatureAllowed, + //publicKeys := make([]ed25519.PublicKey, 0, 3) + //for _, hexStr := range []string{ + // "9fa007ac1e01b426c413de7516e326146af91a38d6910b58e5c5b52c9a3fca40", + // "7083e317cf2ea0ad8cc0e9eda6bac78e41408c562d15b37473fa4c3d5b0b1184", + // "7acc556f12b26e086806b473dee1cc3c0595af7e9433be461025d9a973bfb0e8", + //} { + // pk, err := tonconnect.DecodePublicKey(hexStr) + // if err != nil { + // panic(err) + // } + // publicKeys = append(publicKeys, pk) + //} + + // Define the byte slices + byteArrays := [][]byte{ + {159, 160, 7, 172, 30, 1, 180, 38, 196, 19, 222, 117, 22, 227, 38, 20, 106, 249, 26, 56, 214, 145, 11, 88, 229, 197, 181, 44, 154, 63, 202, 64}, + {112, 131, 227, 23, 207, 46, 160, 173, 140, 192, 233, 237, 166, 186, 199, 142, 65, 64, 140, 86, 45, 21, 179, 116, 115, 250, 76, 61, 91, 11, 17, 132}, + {122, 204, 85, 111, 18, 178, 110, 8, 104, 6, 180, 115, 222, 225, 204, 60, 5, 149, 175, 126, 148, 51, 190, 70, 16, 37, 217, 169, 115, 191, 176, 232}, + } + var adminKeys tlb.HashmapE[tlb.Bits256, bool] + for _, key := range byteArrays { + adminKeys.Put(publicKeyToBits(key), true) + } + data := BlumWalletData{ + Version: 0, Seqno: 0, - WalletID: w.walletID, + WalletID: 0, PublicKey: publicKeyToBits(w.publicKey), + IsFrozen: false, + MinSigAmount: 2, + AdminKeys: adminKeys, + SingleSuspendSeqno: 0, + MassSuspendSeqno: 0, } return generateStateInit(V5R1, data) } @@ -89,22 +129,30 @@ type extV5R1SignedMessage struct { ExtendedActions *W5ExtendedActions `tlb:"maybe"` } +type blumSignedMessage struct { + WalletId uint32 + ValidUntil uint32 + Seqno uint32 + Actions *BlumActions `tlb:"maybe^"` +} + func (w *walletV5R1) CreateSignedMsgBodyCell(privateKey ed25519.PrivateKey, internalMessages []RawMessage, extensionsActions *W5ExtendedActions, msgConfig MessageConfig) (*boc.Cell, error) { - actions := make([]W5SendMessageAction, 0, len(internalMessages)) + actions := make([]BlumSendMessageAction, 0, len(internalMessages)) for _, msg := range internalMessages { - actions = append(actions, W5SendMessageAction{ + actions = append(actions, BlumSendMessageAction{ Msg: msg.Message, Mode: msg.Mode, }) } - w5Actions := W5Actions(actions) - msg := extV5R1SignedMessage{ - WalletId: w.walletID, - ValidUntil: uint32(msgConfig.ValidUntil.Unix()), - Seqno: msgConfig.Seqno, - Actions: &w5Actions, - ExtendedActions: extensionsActions, + blumActions := BlumActions(actions) + + msg := blumSignedMessage{ + WalletId: w.walletID, + ValidUntil: uint32(msgConfig.ValidUntil.Unix()), + Seqno: msgConfig.Seqno, + Actions: &blumActions, } + bodyCell := boc.NewCell() if err := bodyCell.WriteUint(uint64(msgConfig.V5MsgType), 32); err != nil { return nil, err @@ -128,13 +176,13 @@ func (w *walletV5R1) createSignedMsgBodyCell(privateKey ed25519.PrivateKey, inte func (w *walletV5R1) NextMessageParams(state tlb.ShardAccount) (NextMsgParams, error) { if state.Account.Status() == tlb.AccountActive { - var data DataV5R1 + var data BlumWalletData 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{ - Seqno: uint32(data.Seqno), + Seqno: data.Seqno, }, nil } init, err := w.generateStateInit() @@ -144,35 +192,6 @@ func (w *walletV5R1) NextMessageParams(state tlb.ShardAccount) (NextMsgParams, e return NextMsgParams{Init: init}, nil } -func (w *walletV5R1) CreateMsgBodyWithoutSignature(internalMessages []RawMessage, msgConfig MessageConfig) (*boc.Cell, error) { - actions := make([]W5SendMessageAction, 0, len(internalMessages)) - for _, msg := range internalMessages { - actions = append(actions, W5SendMessageAction{ - Msg: msg.Message, - Mode: msg.Mode, - }) - } - w5Actions := W5Actions(actions) - msg := extV5R1SignedMessage{ - WalletId: w.walletID, - ValidUntil: uint32(msgConfig.ValidUntil.Unix()), - Seqno: msgConfig.Seqno, - Actions: &w5Actions, - } - 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 -} - // GetW5R1ExtensionsList returns a list of wallet v5 extensions added to a specific wallet. func GetW5R1ExtensionsList(state tlb.ShardAccount, workchain int) (map[ton.AccountID]struct{}, error) { if state.Account.Status() == tlb.AccountActive { From 24a4555c956409055bfc688177870f8e92788cc6 Mon Sep 17 00:00:00 2001 From: Victoria Erokhina Date: Wed, 30 Apr 2025 11:21:24 +0000 Subject: [PATCH 3/5] test --- wallet/messages.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/wallet/messages.go b/wallet/messages.go index c6d2e136..229be5a0 100644 --- a/wallet/messages.go +++ b/wallet/messages.go @@ -327,6 +327,12 @@ func VerifySignature(ver Version, msg *boc.Cell, publicKey ed25519.PublicKey) er return err } return signedMsgBody.Verify(publicKey) + case V5R1: + var m tlb.Message + if err := tlb.Unmarshal(msg, &m); err != nil { + return err + } + return MessageV5VerifySignature(boc.Cell(m.Body.Value), publicKey) default: return fmt.Errorf("wallet version is not supported: %v", ver) } From 9b2628f5cffb947e3644b1b2061f931460484374 Mon Sep 17 00:00:00 2001 From: Victoria Erokhina Date: Wed, 30 Apr 2025 11:22:38 +0000 Subject: [PATCH 4/5] test --- wallet/wallet_v5.go | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/wallet/wallet_v5.go b/wallet/wallet_v5.go index 24ea3cd7..766b2776 100644 --- a/wallet/wallet_v5.go +++ b/wallet/wallet_v5.go @@ -192,6 +192,35 @@ func (w *walletV5R1) NextMessageParams(state tlb.ShardAccount) (NextMsgParams, e return NextMsgParams{Init: init}, nil } +func (w *walletV5R1) CreateMsgBodyWithoutSignature(internalMessages []RawMessage, msgConfig MessageConfig) (*boc.Cell, error) { + actions := make([]W5SendMessageAction, 0, len(internalMessages)) + for _, msg := range internalMessages { + actions = append(actions, W5SendMessageAction{ + Msg: msg.Message, + Mode: msg.Mode, + }) + } + w5Actions := W5Actions(actions) + msg := extV5R1SignedMessage{ + WalletId: w.walletID, + ValidUntil: uint32(msgConfig.ValidUntil.Unix()), + Seqno: msgConfig.Seqno, + Actions: &w5Actions, + } + 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 +} + // GetW5R1ExtensionsList returns a list of wallet v5 extensions added to a specific wallet. func GetW5R1ExtensionsList(state tlb.ShardAccount, workchain int) (map[ton.AccountID]struct{}, error) { if state.Account.Status() == tlb.AccountActive { From 6603cfc1843449405319b4bdd23ba17489d7a702 Mon Sep 17 00:00:00 2001 From: Victoria Erokhina Date: Tue, 6 May 2025 12:30:51 +0000 Subject: [PATCH 5/5] test --- wallet/wallet.go | 6 +++--- wallet/wallet_v5.go | 32 ++------------------------------ 2 files changed, 5 insertions(+), 33 deletions(-) diff --git a/wallet/wallet.go b/wallet/wallet.go index f8184479..5249fe51 100644 --- a/wallet/wallet.go +++ b/wallet/wallet.go @@ -215,9 +215,8 @@ func (w *Wallet) RawSendV2( if err != nil { return ton.Bits256{}, fmt.Errorf("can not serialize external message cell: %v", err) } - //fmt.Println(base64.StdEncoding.EncodeToString(payload)) - t := time.Now() + fmt.Printf("%x\n", payload) _, err = w.blockchain.SendMessage(ctx, payload) // TODO: add result code check if err != nil { return msgHash, err @@ -259,7 +258,8 @@ func (w *Wallet) SendV2(ctx context.Context, waitingConfirmation time.Duration, if w.blockchain == nil { return ton.Bits256{}, errors.New("blockchain interface is nil") } - state, err := w.blockchain.GetAccountState(ctx, w.GetAddress()) + walletAddress := ton.MustParseAccountID("kQDaJW6wJyc_Fpn042zXsRJcpdkomc-J-bYucBClO3N6KWny") + state, err := w.blockchain.GetAccountState(ctx, walletAddress) if err != nil { return ton.Bits256{}, fmt.Errorf("get account state failed: %v", err) } diff --git a/wallet/wallet_v5.go b/wallet/wallet_v5.go index 766b2776..25b66cb6 100644 --- a/wallet/wallet_v5.go +++ b/wallet/wallet_v5.go @@ -147,7 +147,8 @@ func (w *walletV5R1) CreateSignedMsgBodyCell(privateKey ed25519.PrivateKey, inte blumActions := BlumActions(actions) msg := blumSignedMessage{ - WalletId: w.walletID, + //WalletId: w.walletID, + WalletId: 0, ValidUntil: uint32(msgConfig.ValidUntil.Unix()), Seqno: msgConfig.Seqno, Actions: &blumActions, @@ -192,35 +193,6 @@ func (w *walletV5R1) NextMessageParams(state tlb.ShardAccount) (NextMsgParams, e return NextMsgParams{Init: init}, nil } -func (w *walletV5R1) CreateMsgBodyWithoutSignature(internalMessages []RawMessage, msgConfig MessageConfig) (*boc.Cell, error) { - actions := make([]W5SendMessageAction, 0, len(internalMessages)) - for _, msg := range internalMessages { - actions = append(actions, W5SendMessageAction{ - Msg: msg.Message, - Mode: msg.Mode, - }) - } - w5Actions := W5Actions(actions) - msg := extV5R1SignedMessage{ - WalletId: w.walletID, - ValidUntil: uint32(msgConfig.ValidUntil.Unix()), - Seqno: msgConfig.Seqno, - Actions: &w5Actions, - } - 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 -} - // GetW5R1ExtensionsList returns a list of wallet v5 extensions added to a specific wallet. func GetW5R1ExtensionsList(state tlb.ShardAccount, workchain int) (map[ton.AccountID]struct{}, error) { if state.Account.Status() == tlb.AccountActive {