Documentation
¶
Index ¶
- Constants
- Variables
- func AmountInterval(min, max int64) bubbleCheck
- func CollectActionsAndValueFlow(bubble *Bubble, forAccount *tongo.AccountID) ([]Action, *ValueFlow)
- func HasEmptyBody(b *Bubble) bool
- func HasInterface(iface abi.ContractInterface) bubbleCheck
- func HasOpcode(op uint32) bubbleCheck
- func HasOperation(name abi.MsgOpName) bubbleCheck
- func HasTextComment(comment string) bubbleCheck
- func Is(t actioner) bubbleCheck
- func IsAccount(id tongo.AccountID) bubbleCheck
- func IsBounced(bubble *Bubble) bool
- func IsJettonReceiver(iface abi.ContractInterface) bubbleCheck
- func IsJettonTransfer(b *Bubble) bool
- func IsNftTransfer(b *Bubble) bool
- func IsTx(b *Bubble) bool
- func JettonTransferOpCode(opCode uint32) bubbleCheck
- func JettonTransferOperation(op abi.JettonOpName) bubbleCheck
- func MergeAllBubbles(bubble *Bubble, straws []Merger)
- func Or(check1, check2 bubbleCheck) bubbleCheck
- type Account
- type AccountValueFlow
- type Action
- type ActionType
- type ActionsList
- type AuctionBidAction
- type AuctionBidBubble
- type Bubble
- type BubbleContractDeploy
- type BubbleDepositStake
- type BubbleDnsItemRenew
- type BubbleElectionsDepositStake
- type BubbleElectionsRecoverStake
- type BubbleInvoicePayment
- type BubbleJettonBurn
- type BubbleJettonMint
- type BubbleJettonSwap
- type BubbleJettonTransfer
- type BubbleNftPurchase
- type BubbleNftTransfer
- type BubbleSubscription
- type BubbleTx
- type BubbleUnSubscription
- type BubbleWithdrawStake
- type BubbleWithdrawStakeRequest
- type ContractDeployAction
- type ContractDeployment
- type DepositStakeAction
- type Dex
- type DnsRenewAction
- type ElectionsDepositStakeAction
- type ElectionsRecoverStakeAction
- type EncryptedComment
- type ExtraCurrencyTransferAction
- type GasRelayAction
- type GasRelayBubble
- type JettonBurnAction
- type JettonMintAction
- type JettonSwapAction
- type JettonTransferAction
- type Merge
- type Merger
- type NftAuctionType
- type NftPurchaseAction
- type NftTransferAction
- type Option
- type Options
- type OutMessage
- type PurchaseAction
- type Refund
- type RefundType
- type SmartContractAction
- type Straw
- type SubscriptionAction
- type TonTransferAction
- type UnSubscriptionAction
- type UniversalDedustStraw
- type ValueFlow
- func (flow *ValueFlow) AddFee(accountID tongo.AccountID, amount int64)
- func (flow *ValueFlow) AddJettons(accountID tongo.AccountID, jettonMaster tongo.AccountID, value big.Int)
- func (flow *ValueFlow) AddTons(accountID tongo.AccountID, amount int64)
- func (flow *ValueFlow) Merge(other *ValueFlow)
- func (flow *ValueFlow) SubJettons(accountID tongo.AccountID, jettonMaster tongo.AccountID, value big.Int)
- type WithdrawStakeAction
- type WithdrawStakeRequestAction
Constants ¶
const ( GetGemsAuction NftAuctionType = "getgems" DnsTonAuction = "DNS.ton" DnsTgAuction = "DNS.tg" NumberTgAuction = "NUMBER.tg" )
Variables ¶
var DNSRenewStraw = Straw[BubbleDnsItemRenew]{ CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.DeleteDnsRecordMsgOp), HasInterface(abi.NftItem), func(bubble *Bubble) bool { return bubble.Info.(BubbleTx).decodedBody.Value.(abi.DeleteDnsRecordMsgBody).Key.Equal(tlb.Bits256{}) }}, Builder: func(newAction *BubbleDnsItemRenew, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) newAction.Renewer = tx.inputFrom.Address newAction.Item = tx.account.Address newAction.Success = tx.success return nil }, SingleChild: &Straw[BubbleDnsItemRenew]{ Optional: true, CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.BounceMsgOp)}, }, }
var DefaultStraws = []Merger{ StrawFindAuctionBidFragmentSimple, GasRelayerStraw, NftTransferStraw, NftTransferNotifyStraw, StonfiV1PTONStraw, StonfiV2PTONStrawReverse, StonfiV2PTONStraw, JettonTransferClassicStraw, JettonTransferMinimalStraw, JettonBurnStraw, WtonMintStraw, NftPurchaseStraw, StonfiSwapStraw, StonfiSwapV2Straw, UniversalDedustStraw{}, TgAuctionV1InitialBidStraw, StrawAuctionBigGetgems, StrawAuctionBuyGetgems, StrawAuctionBuyFragments, JettonMintFromMasterStraw, JettonMintStrawGovernance, InvoicePaymentStrawNative, InvoicePaymentStrawJetton, MegatonFiJettonSwap, InitialSubscriptionStraw, ExtendedSubscriptionStraw, UnSubscriptionStraw, DepositLiquidStakeStraw, PendingWithdrawRequestLiquidStraw, ElectionsDepositStakeStraw, ElectionsRecoverStakeStraw, DepositTFStakeStraw, WithdrawTFStakeRequestStraw, WithdrawStakeImmediatelyStraw, WithdrawLiquidStake, DNSRenewStraw, }
var DepositLiquidStakeStraw = Straw[BubbleDepositStake]{ CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.TonstakePoolDepositMsgOp)}, Builder: func(newAction *BubbleDepositStake, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) newAction.Pool = tx.account.Address newAction.Staker = tx.inputFrom.Address newAction.Amount = tx.inputAmount - int64(ton.OneTON) if newAction.Amount < 0 { newAction.Amount = 0 } newAction.Success = tx.success newAction.Implementation = core.StakingImplementationLiquidTF return nil }, SingleChild: &Straw[BubbleDepositStake]{ CheckFuncs: []bubbleCheck{IsBounced}, Optional: true, }, }
var DepositTFStakeStraw = Straw[BubbleDepositStake]{ CheckFuncs: []bubbleCheck{IsTx, HasInterface(abi.TvPool), HasTextComment("d")}, Builder: func(newAction *BubbleDepositStake, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) newAction.Pool = tx.account.Address newAction.Staker = tx.inputFrom.Address newAction.Amount = tx.inputAmount newAction.Success = tx.success newAction.Implementation = core.StakingImplementationTF return nil }, SingleChild: &Straw[BubbleDepositStake]{ CheckFuncs: []bubbleCheck{IsBounced}, Optional: true, }, }
var ElectionsDepositStakeStraw = Straw[BubbleElectionsDepositStake]{ CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.ElectorNewStakeMsgOp), IsAccount(config.ElectorAddress())}, Builder: func(newAction *BubbleElectionsDepositStake, bubble *Bubble) error { bubbleTx := bubble.Info.(BubbleTx) newAction.Amount = bubbleTx.inputAmount newAction.Staker = bubbleTx.inputFrom.Address return nil }, Children: []Straw[BubbleElectionsDepositStake]{ { CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.ElectorNewStakeConfirmationMsgOp)}, Builder: func(newAction *BubbleElectionsDepositStake, bubble *Bubble) error { newAction.Success = true return nil }, }, }, }
var ElectionsRecoverStakeStraw = Straw[BubbleElectionsRecoverStake]{ CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.ElectorRecoverStakeRequestMsgOp), IsAccount(config.ElectorAddress())}, Builder: func(newAction *BubbleElectionsRecoverStake, bubble *Bubble) error { bubbleTx := bubble.Info.(BubbleTx) newAction.Staker = bubbleTx.inputFrom.Address return nil }, Children: []Straw[BubbleElectionsRecoverStake]{ { CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.ElectorRecoverStakeResponseMsgOp)}, Builder: func(newAction *BubbleElectionsRecoverStake, bubble *Bubble) error { newAction.Amount = bubble.Info.(BubbleTx).inputAmount newAction.Success = true return nil }, }, }, }
var ExtendedSubscriptionStraw = Straw[BubbleSubscription]{ CheckFuncs: []bubbleCheck{IsTx, HasInterface(abi.SubscriptionV1)}, Builder: func(newAction *BubbleSubscription, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) newAction.Subscription = tx.account return nil }, SingleChild: &Straw[BubbleSubscription]{ CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.PaymentRequestMsgOp)}, Builder: func(newAction *BubbleSubscription, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) request := tx.decodedBody.Value.(abi.PaymentRequestMsgBody) newAction.Subscriber = tx.account newAction.Success = tx.success newAction.Amount = int64(request.Amount.Grams) return nil }, SingleChild: &Straw[BubbleSubscription]{ Optional: true, CheckFuncs: []bubbleCheck{HasInterface(abi.SubscriptionV1)}, SingleChild: &Straw[BubbleSubscription]{ Optional: true, CheckFuncs: []bubbleCheck{HasOperation(abi.SubscriptionPaymentMsgOp)}, Builder: func(newAction *BubbleSubscription, bubble *Bubble) error { sub := bubble.Info.(BubbleTx) newAction.First = false newAction.Beneficiary = sub.account newAction.Success = true return nil }, }, }, }, }
var GasRelayerStraw = Straw[GasRelayBubble]{ CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.WalletSignedInternalV5R1MsgOp), HasInterface(abi.WalletV5R1), func(bubble *Bubble) bool { tx := bubble.Info.(BubbleTx) return tx.inputFrom != nil && slices.Contains(knownRelayers, tx.inputFrom.Address) }}, Builder: func(newAction *GasRelayBubble, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) newAction.Relayer = tx.inputFrom.Address newAction.Target = tx.account.Address newAction.Amount = tx.inputAmount return nil }, }
var InitialSubscriptionStraw = Straw[BubbleSubscription]{ CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.PaymentRequestResponseMsgOp), AmountInterval(1, 1<<62)}, Builder: func(newAction *BubbleSubscription, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) newAction.Subscriber = *tx.inputFrom newAction.Subscription = tx.account newAction.Amount = tx.inputAmount newAction.First = len(tx.init) != 0 return nil }, SingleChild: &Straw[BubbleSubscription]{ CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.SubscriptionPaymentMsgOp)}, Builder: func(newAction *BubbleSubscription, bubble *Bubble) error { newAction.Success = true newAction.Beneficiary = bubble.Info.(BubbleTx).account return nil }, }, }
var InvoicePaymentStrawJetton = Straw[BubbleInvoicePayment]{ CheckFuncs: []bubbleCheck{func(bubble *Bubble) bool { jettonTx, ok := bubble.Info.(BubbleJettonTransfer) if !ok { return false } if jettonTx.sender == nil || jettonTx.recipient == nil { return false } if jettonTx.payload.SumType != abi.InvoicePayloadJettonOp { return false } return true }}, Builder: func(newAction *BubbleInvoicePayment, bubble *Bubble) error { jettonTx := bubble.Info.(BubbleJettonTransfer) invoicePayload := jettonTx.payload.Value.(abi.InvoicePayloadJettonPayload) id, err := uuid.FromBytes(invoicePayload.Id[:]) if err != nil { return err } newAction.InvoiceID = id newAction.Price = core.Price{ Currency: core.Currency{ Type: core.CurrencyJetton, Jetton: &jettonTx.master, }, Amount: big.Int(jettonTx.amount), } newAction.Sender = jettonTx.sender.Address newAction.Recipient = jettonTx.recipient.Address newAction.Success = jettonTx.success return nil }, }
var InvoicePaymentStrawNative = Straw[BubbleInvoicePayment]{ CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.InvoicePayloadMsgOp), AmountInterval(1, 1<<62)}, Builder: func(newAction *BubbleInvoicePayment, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) invoicePayload := tx.decodedBody.Value.(abi.InvoicePayloadMsgBody) id, err := uuid.FromBytes(invoicePayload.Id[:]) if err != nil { return err } newAction.InvoiceID = id price := core.Price{ Currency: core.Currency{Type: core.CurrencyTON}, Amount: *big.NewInt(tx.inputAmount), } for c, am := range tx.inputExtraAmount { price.Currency = core.Currency{ Type: core.CurrencyExtra, CurrencyID: &c, } price.Amount = big.Int(am) break } if tx.inputFrom == nil { return errors.New("empty input") } newAction.Sender = tx.inputFrom.Address newAction.Recipient = tx.account.Address newAction.Price = price newAction.Success = tx.success return nil }, }
var JettonBurnStraw = Straw[BubbleJettonBurn]{ CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.JettonBurnMsgOp)}, Builder: func(newAction *BubbleJettonBurn, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) msg := tx.decodedBody.Value.(abi.JettonBurnMsgBody) newAction.amount = msg.Amount if tx.inputFrom != nil { newAction.sender = *tx.inputFrom } if tx.additionalInfo != nil { if master, ok := tx.additionalInfo.JettonMaster(tx.account.Address); ok { newAction.master = master } } newAction.senderWallet = tx.account.Address newAction.success = tx.success return nil }, SingleChild: &Straw[BubbleJettonBurn]{ CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.JettonBurnNotificationMsgOp)}, Builder: func(newAction *BubbleJettonBurn, bubble *Bubble) error { newAction.master = bubble.Info.(BubbleTx).account.Address return nil }, Optional: true, }, }
var JettonMintFromMasterStraw = Straw[BubbleJettonMint]{ CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.JettonInternalTransferMsgOp), HasInterface(abi.JettonWallet), func(bubble *Bubble) bool { tx := bubble.Info.(BubbleTx) return tx.inputFrom != nil && tx.inputFrom.Is(abi.JettonMaster) }}, Builder: func(newAction *BubbleJettonMint, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) msg := tx.decodedBody.Value.(abi.JettonInternalTransferMsgBody) newAction.amount = msg.Amount newAction.master = tx.inputFrom.Address newAction.recipientWallet = tx.account.Address newAction.success = tx.success return nil }, Children: []Straw[BubbleJettonMint]{ { CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.JettonNotifyMsgOp)}, Builder: func(newAction *BubbleJettonMint, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) newAction.recipient = tx.account return nil }, }, {CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.ExcessMsgOp)}, Optional: true}, }, }
JettonMintFromMasterStraw example: https://tonviewer.com/transaction/6d33487c44249d7844db8fac38a5cecf1502ec7e0c09d266e98e95a2b1be17b5
var JettonMintStrawGovernance = Straw[BubbleJettonMint]{ CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.JettonMintMsgOp), HasInterface(abi.JettonMaster)}, Builder: func(newAction *BubbleJettonMint, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) msg := tx.decodedBody.Value.(abi.JettonMintMsgBody) dest, err := tongo.AccountIDFromTlb(msg.ToAddress) if err == nil && dest != nil { newAction.recipient = Account{Address: *dest} } return nil }, SingleChild: &Straw[BubbleJettonMint]{ CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.JettonInternalTransferMsgOp), HasInterface(abi.JettonWallet)}, Builder: func(newAction *BubbleJettonMint, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) msg := tx.decodedBody.Value.(abi.JettonInternalTransferMsgBody) newAction.amount = msg.Amount newAction.recipientWallet = tx.account.Address newAction.master = tx.inputFrom.Address newAction.success = tx.success return nil }, SingleChild: &Straw[BubbleJettonMint]{ Optional: true, CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.ExcessMsgOp)}, }, }, }
var JettonTransferClassicStraw = Straw[BubbleJettonTransfer]{ CheckFuncs: []bubbleCheck{IsTx, HasInterface(abi.JettonWallet), HasOperation(abi.JettonTransferMsgOp)}, Builder: func(newAction *BubbleJettonTransfer, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) newAction.master, _ = tx.additionalInfo.JettonMaster(tx.account.Address) newAction.senderWallet = tx.account.Address newAction.sender = tx.inputFrom body := tx.decodedBody.Value.(abi.JettonTransferMsgBody) newAction.amount = body.Amount newAction.payload = body.ForwardPayload.Value recipient, err := ton.AccountIDFromTlb(body.Destination) if err == nil && recipient != nil { newAction.recipient = &Account{Address: *recipient} bubble.Accounts = append(bubble.Accounts, *recipient) } return nil }, SingleChild: &Straw[BubbleJettonTransfer]{ CheckFuncs: []bubbleCheck{IsTx, Or(HasInterface(abi.JettonWallet), HasOperation(abi.JettonInternalTransferMsgOp))}, Optional: true, Builder: func(newAction *BubbleJettonTransfer, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) newAction.recipientWallet = tx.account.Address if newAction.master.IsZero() { newAction.master, _ = tx.additionalInfo.JettonMaster(tx.account.Address) } newAction.success = tx.success return nil }, ValueFlowUpdater: func(newAction *BubbleJettonTransfer, flow *ValueFlow) { if newAction.success { if newAction.recipient != nil { flow.AddJettons(newAction.recipient.Address, newAction.master, big.Int(newAction.amount)) } if newAction.sender != nil { flow.SubJettons(newAction.sender.Address, newAction.master, big.Int(newAction.amount)) } } }, Children: []Straw[BubbleJettonTransfer]{ { CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.JettonNotifyMsgOp)}, Builder: func(newAction *BubbleJettonTransfer, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) newAction.success = true body := tx.decodedBody.Value.(abi.JettonNotifyMsgBody) newAction.amount = body.Amount newAction.payload = body.ForwardPayload.Value newAction.recipient = &tx.account if newAction.sender == nil { sender, err := ton.AccountIDFromTlb(body.Sender) if err == nil { newAction.sender = &Account{Address: *sender} } } return nil }, ValueFlowUpdater: func(newAction *BubbleJettonTransfer, flow *ValueFlow) { if newAction.recipient != nil { flow.AddJettons(newAction.recipient.Address, newAction.master, big.Int(newAction.amount)) } if newAction.sender != nil { flow.SubJettons(newAction.sender.Address, newAction.master, big.Int(newAction.amount)) } }, Optional: true, }, { CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.ExcessMsgOp)}, Optional: true, }, }, }, }
var JettonTransferMinimalStraw = Straw[BubbleJettonTransfer]{ CheckFuncs: []bubbleCheck{IsTx, HasInterface(abi.JettonWallet), HasOpcode(abi.JettonTransferMsgOpCode)}, Builder: func(newAction *BubbleJettonTransfer, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) newAction.master, _ = tx.additionalInfo.JettonMaster(tx.account.Address) newAction.senderWallet = tx.account.Address newAction.sender = tx.inputFrom return nil }, SingleChild: &Straw[BubbleJettonTransfer]{ CheckFuncs: []bubbleCheck{IsTx, HasInterface(abi.JettonWallet), HasOperation(abi.JettonInternalTransferMsgOp)}, Optional: true, Builder: func(newAction *BubbleJettonTransfer, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) newAction.recipientWallet = tx.account.Address if newAction.master.IsZero() { newAction.master, _ = tx.additionalInfo.JettonMaster(tx.account.Address) } newAction.success = tx.success body, _ := tx.decodedBody.Value.(abi.JettonInternalTransferMsgBody) newAction.amount = body.Amount return nil }, ValueFlowUpdater: func(newAction *BubbleJettonTransfer, flow *ValueFlow) { if newAction.success { if newAction.recipient != nil { flow.AddJettons(newAction.recipient.Address, newAction.master, big.Int(newAction.amount)) } if newAction.sender != nil { flow.SubJettons(newAction.sender.Address, newAction.master, big.Int(newAction.amount)) } } }, Children: []Straw[BubbleJettonTransfer]{ { CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.JettonNotifyMsgOp)}, Builder: func(newAction *BubbleJettonTransfer, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) newAction.success = true body := tx.decodedBody.Value.(abi.JettonNotifyMsgBody) newAction.amount = body.Amount newAction.payload = body.ForwardPayload.Value newAction.recipient = &tx.account if newAction.sender == nil { sender, err := ton.AccountIDFromTlb(body.Sender) if err == nil { newAction.sender = &Account{Address: *sender} } } return nil }, ValueFlowUpdater: func(newAction *BubbleJettonTransfer, flow *ValueFlow) { if newAction.recipient != nil { flow.AddJettons(newAction.recipient.Address, newAction.master, big.Int(newAction.amount)) } if newAction.sender != nil { flow.SubJettons(newAction.sender.Address, newAction.master, big.Int(newAction.amount)) } }, Optional: true, }, { CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.ExcessMsgOp)}, Optional: true, }, }, }, }
var JettonTransfersBurnsMints = []Merger{ StonfiV1PTONStraw, StonfiV2PTONStrawReverse, StonfiV2PTONStraw, JettonTransferClassicStraw, JettonTransferMinimalStraw, JettonBurnStraw, JettonMintFromMasterStraw, JettonMintStrawGovernance, WtonMintStraw, }
var MegatonFiJettonSwap = Straw[BubbleJettonSwap]{ CheckFuncs: []bubbleCheck{IsJettonTransfer, IsJettonReceiver(abi.MegatonfiRouter)}, Builder: func(newAction *BubbleJettonSwap, bubble *Bubble) error { tx := bubble.Info.(BubbleJettonTransfer) newAction.UserWallet = tx.sender.Address newAction.In.Amount = big.Int(tx.amount) newAction.In.IsTon = tx.isWrappedTon newAction.Router = tx.recipient.Address newAction.In.JettonWallet = tx.senderWallet newAction.In.JettonMaster = tx.master newAction.Dex = Megatonfi return nil }, Children: []Straw[BubbleJettonSwap]{ { CheckFuncs: []bubbleCheck{IsJettonTransfer, IsJettonReceiver(abi.MegatonfiExchange)}, Children: []Straw[BubbleJettonSwap]{ { CheckFuncs: []bubbleCheck{IsJettonTransfer, IsJettonReceiver(abi.MegatonfiRouter)}, Children: []Straw[BubbleJettonSwap]{ { CheckFuncs: []bubbleCheck{IsJettonTransfer}, Builder: func(newAction *BubbleJettonSwap, bubble *Bubble) error { tx := bubble.Info.(BubbleJettonTransfer) newAction.Success = tx.success newAction.Out.Amount = big.Int(tx.amount) newAction.Out.IsTon = tx.isWrappedTon newAction.Out.JettonWallet = tx.recipientWallet newAction.Out.JettonMaster = tx.master return nil }, }, }, }, }, }, }, }
MegatonFiJettonSwap creates a BubbleJettonSwap if there is a jetton swap in a trace.
var NFTStraws = []Merger{ NftTransferStraw, NftTransferNotifyStraw, }
var NftPurchaseStraw = Straw[BubbleNftPurchase]{ CheckFuncs: []bubbleCheck{ IsTx, Or(HasInterface(abi.NftSaleV2), HasInterface(abi.NftSaleV1)), HasEmptyBody, AmountInterval(1, 1<<62), func(bubble *Bubble) bool { tx := bubble.Info.(BubbleTx) return tx.additionalInfo != nil && tx.additionalInfo.NftSaleContract != nil && tx.additionalInfo.NftSaleContract.Owner != nil }}, Builder: func(newAction *BubbleNftPurchase, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) sale := tx.additionalInfo.NftSaleContract newAction.Seller = *sale.Owner newAction.AuctionType = GetGemsAuction newAction.Buyer = tx.inputFrom.Address newAction.Price = sale.NftPrice if tx.additionalInfo.NftSaleContract != nil { newAction.Nft = tx.additionalInfo.NftSaleContract.Item } return nil }, SingleChild: &Straw[BubbleNftPurchase]{ CheckFuncs: []bubbleCheck{IsNftTransfer}, Builder: func(newAction *BubbleNftPurchase, bubble *Bubble) error { newAction.Success = bubble.Info.(BubbleNftTransfer).success newAction.Nft = bubble.Info.(BubbleNftTransfer).account.Address return nil }, Optional: true, }, }
var NftTransferNotifyStraw = Straw[BubbleNftTransfer]{ CheckFuncs: []bubbleCheck{IsTx, HasInterface(abi.NftItem)}, Builder: func(newAction *BubbleNftTransfer, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) if tx.inputFrom != nil { newAction.sender = tx.inputFrom } return nil }, Children: []Straw[BubbleNftTransfer]{ { CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.NftOwnershipAssignedMsgOp)}, Builder: func(newAction *BubbleNftTransfer, bubble *Bubble) error { receiverTx := bubble.Info.(BubbleTx) transfer := receiverTx.decodedBody.Value.(abi.NftOwnershipAssignedMsgBody) newAction.success = true if receiverTx.inputFrom == nil { return fmt.Errorf("nft transfer notify without sender") } newAction.account = *receiverTx.inputFrom newAction.recipient = &receiverTx.account newAction.payload = transfer.ForwardPayload.Value return nil }, }, { CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.ExcessMsgOp)}, Optional: true, }, }, }
var NftTransferStraw = Straw[BubbleNftTransfer]{ CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.NftTransferMsgOp), HasInterface(abi.NftItem)}, Builder: func(newAction *BubbleNftTransfer, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) transfer := tx.decodedBody.Value.(abi.NftTransferMsgBody) newAction.account = tx.account newAction.success = tx.success newAction.sender = tx.inputFrom newAction.payload = transfer.ForwardPayload.Value if newAction.recipient == nil { newAction.recipient = parseAccount(transfer.NewOwner) if newAction.recipient != nil { bubble.Accounts = append(bubble.Accounts, newAction.recipient.Address) } } return nil }, Children: []Straw[BubbleNftTransfer]{ { CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.NftOwnershipAssignedMsgOp)}, Optional: true, Builder: func(newAction *BubbleNftTransfer, bubble *Bubble) error { receiverTx := bubble.Info.(BubbleTx) transfer := receiverTx.decodedBody.Value.(abi.NftOwnershipAssignedMsgBody) newAction.success = true newAction.payload = transfer.ForwardPayload.Value return nil }, }, { CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.ExcessMsgOp)}, Optional: true, }, }, }
var PendingWithdrawRequestLiquidStraw = Straw[BubbleWithdrawStakeRequest]{ CheckFuncs: []bubbleCheck{Is(BubbleJettonBurn{})}, Builder: func(newAction *BubbleWithdrawStakeRequest, bubble *Bubble) error { newAction.Staker = bubble.Info.(BubbleJettonBurn).sender.Address newAction.Success = true newAction.Implementation = core.StakingImplementationLiquidTF amount := big.Int(bubble.Info.(BubbleJettonBurn).amount) i := amount.Int64() newAction.Amount = &i return nil }, SingleChild: &Straw[BubbleWithdrawStakeRequest]{ CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.TonstakePoolWithdrawMsgOp)}, Builder: func(newAction *BubbleWithdrawStakeRequest, bubble *Bubble) error { newAction.Pool = bubble.Info.(BubbleTx).account.Address newAction.Success = true newAction.attachedAmount = bubble.Info.(BubbleTx).inputAmount return nil }, SingleChild: &Straw[BubbleWithdrawStakeRequest]{ Optional: true, CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.TonstakePayoutMintJettonsMsgOp)}, SingleChild: &Straw[BubbleWithdrawStakeRequest]{ CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.TonstakeNftInitMsgOp)}, SingleChild: &Straw[BubbleWithdrawStakeRequest]{ CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.NftOwnershipAssignedMsgOp)}, Builder: func(newAction *BubbleWithdrawStakeRequest, bubble *Bubble) error { newAction.Success = true return nil }, }, }, }, }, }
var StonfiMintStraw = Straw[BubbleJettonMint]{}
https://dev.tonviewer.com/transaction/e19381edd8f05922eeba3c31f4b8b4b737478b4ca7b37130bdbbfd7bfa773227 todo: add liquidity (mint lp tokens)
var StonfiSwapStraw = Straw[BubbleJettonSwap]{ CheckFuncs: []bubbleCheck{func(bubble *Bubble) bool { jettonTx, ok := bubble.Info.(BubbleJettonTransfer) if !ok { return false } if jettonTx.sender == nil { return false } if jettonTx.payload.SumType != abi.StonfiSwapJettonOp { return false } swap, ok := jettonTx.payload.Value.(abi.StonfiSwapJettonPayload) if !ok { return false } to, err := ton.AccountIDFromTlb(swap.ToAddress) if err != nil || to == nil { return false } if jettonTx.sender.Address != *to { return false } return true }}, Builder: func(newAction *BubbleJettonSwap, bubble *Bubble) error { newAction.Dex = Stonfi jettonTx := bubble.Info.(BubbleJettonTransfer) newAction.UserWallet = jettonTx.sender.Address newAction.In.Amount = big.Int(jettonTx.amount) newAction.In.IsTon = jettonTx.isWrappedTon newAction.In.JettonMaster = jettonTx.master return nil }, SingleChild: &Straw[BubbleJettonSwap]{ CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.StonfiSwapMsgOp), HasInterface(abi.StonfiPool)}, Builder: func(newAction *BubbleJettonSwap, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) a, b := tx.additionalInfo.STONfiPool.Token0, tx.additionalInfo.STONfiPool.Token1 body := tx.decodedBody.Value.(abi.StonfiSwapMsgBody) newAction.Out.Amount = big.Int(body.MinOut) s, err := tongo.AccountIDFromTlb(body.SenderAddress) if err != nil { return err } if s != nil && *s == b { a, b = b, a } newAction.In.JettonWallet = a newAction.Out.JettonWallet = b if tx.additionalInfo != nil { newAction.In.JettonMaster, _ = tx.additionalInfo.JettonMaster(a) newAction.Out.JettonMaster, _ = tx.additionalInfo.JettonMaster(b) } return nil }, SingleChild: &Straw[BubbleJettonSwap]{ CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.StonfiPaymentRequestMsgOp)}, Builder: func(newAction *BubbleJettonSwap, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) newAction.Router = tx.account.Address return nil }, SingleChild: &Straw[BubbleJettonSwap]{ CheckFuncs: []bubbleCheck{Is(BubbleJettonTransfer{}), Or(JettonTransferOperation(abi.StonfiSwapOkJettonOp), JettonTransferOpCode(0x5ffe1295))}, Builder: func(newAction *BubbleJettonSwap, bubble *Bubble) error { jettonTx := bubble.Info.(BubbleJettonTransfer) if jettonTx.senderWallet != newAction.Out.JettonWallet { return nil } newAction.Out.Amount = big.Int(jettonTx.amount) newAction.Out.IsTon = jettonTx.isWrappedTon newAction.Success = true return nil }, }, }, }, }
var StonfiSwapV2Straw = Straw[BubbleJettonSwap]{ CheckFuncs: []bubbleCheck{func(bubble *Bubble) bool { jettonTx, ok := bubble.Info.(BubbleJettonTransfer) if !ok { return false } if jettonTx.sender == nil { return false } if jettonTx.payload.SumType != abi.StonfiSwapV2JettonOp { return false } swap, ok := jettonTx.payload.Value.(abi.StonfiSwapV2JettonPayload) if !ok { return false } to, err := ton.AccountIDFromTlb(swap.CrossSwapBody.Receiver) if err != nil || to == nil { return false } if jettonTx.sender.Address != *to { return false } return true }}, Builder: func(newAction *BubbleJettonSwap, bubble *Bubble) error { newAction.Dex = Stonfi jettonTx := bubble.Info.(BubbleJettonTransfer) newAction.UserWallet = jettonTx.sender.Address newAction.In.Amount = big.Int(jettonTx.amount) newAction.In.IsTon = jettonTx.isWrappedTon newAction.In.JettonMaster = jettonTx.master return nil }, SingleChild: &Straw[BubbleJettonSwap]{ CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.StonfiSwapV2MsgOp), HasInterface(abi.StonfiPoolV2), func(bubble *Bubble) bool { tx, ok := bubble.Info.(BubbleTx) if !ok { return false } if tx.additionalInfo.STONfiPool == nil { return false } return true }}, Builder: func(newAction *BubbleJettonSwap, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) a, b := tx.additionalInfo.STONfiPool.Token0, tx.additionalInfo.STONfiPool.Token1 body := tx.decodedBody.Value.(abi.StonfiSwapV2MsgBody) if body.QueryId > 0 && a.IsZero() && b.IsZero() { return nil } s, err := tongo.AccountIDFromTlb(body.DexPayload.TokenWallet1) if err != nil { return err } if s != nil && *s == a { a, b = b, a } newAction.In.JettonWallet = a newAction.Out.JettonWallet = b if tx.additionalInfo != nil { newAction.In.JettonMaster, _ = tx.additionalInfo.JettonMaster(a) newAction.Out.JettonMaster, _ = tx.additionalInfo.JettonMaster(b) } return nil }, Children: []Straw[BubbleJettonSwap]{ { CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.StonfiPayToV2MsgOp)}, Builder: func(newAction *BubbleJettonSwap, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) newAction.Router = tx.account.Address return nil }, SingleChild: &Straw[BubbleJettonSwap]{ CheckFuncs: []bubbleCheck{Is(BubbleJettonTransfer{})}, Builder: func(newAction *BubbleJettonSwap, bubble *Bubble) error { jettonTx := bubble.Info.(BubbleJettonTransfer) if jettonTx.senderWallet != newAction.Out.JettonWallet { return nil } newAction.Out.Amount = big.Int(jettonTx.amount) newAction.Out.IsTon = jettonTx.isWrappedTon newAction.Success = true return nil }, }, }, { CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.StonfiPayVaultV2MsgOp)}, Optional: true, SingleChild: &Straw[BubbleJettonSwap]{ CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.StonfiDepositRefFeeV2MsgOp)}, SingleChild: &Straw[BubbleJettonSwap]{ CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.ExcessMsgOp)}, Optional: true, }, }, }, }, }, }
var StonfiV1PTONStraw = Straw[BubbleJettonTransfer]{ CheckFuncs: []bubbleCheck{IsTx, HasInterface(abi.JettonWallet), HasOperation(abi.JettonTransferMsgOp)}, Builder: func(newAction *BubbleJettonTransfer, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) newAction.master, _ = tx.additionalInfo.JettonMaster(tx.account.Address) newAction.senderWallet = tx.account.Address newAction.sender = tx.inputFrom body := tx.decodedBody.Value.(abi.JettonTransferMsgBody) newAction.amount = body.Amount newAction.isWrappedTon = true recipient, err := ton.AccountIDFromTlb(body.Destination) if err == nil && recipient != nil { newAction.recipient = &Account{Address: *recipient} bubble.Accounts = append(bubble.Accounts, *recipient) } return nil }, SingleChild: &Straw[BubbleJettonTransfer]{ CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.JettonNotifyMsgOp)}, Builder: func(newAction *BubbleJettonTransfer, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) newAction.success = true body := tx.decodedBody.Value.(abi.JettonNotifyMsgBody) newAction.amount = body.Amount newAction.payload = body.ForwardPayload.Value newAction.recipient = &tx.account return nil }, }, }
var StonfiV2PTONStraw = Straw[BubbleJettonTransfer]{ CheckFuncs: []bubbleCheck{IsTx, HasInterface(abi.JettonWallet), HasOperation(abi.PtonTonTransferMsgOp)}, Builder: func(newAction *BubbleJettonTransfer, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) newAction.master, _ = tx.additionalInfo.JettonMaster(tx.account.Address) newAction.senderWallet = tx.account.Address newAction.sender = tx.inputFrom body := tx.decodedBody.Value.(abi.PtonTonTransferMsgBody) newAction.amount = tlb.VarUInteger16(*big.NewInt(int64(body.TonAmount))) newAction.isWrappedTon = true recipient, err := ton.AccountIDFromTlb(body.RefundAddress) if err == nil { newAction.recipient = &Account{Address: *recipient} } return nil }, SingleChild: &Straw[BubbleJettonTransfer]{ CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.JettonNotifyMsgOp)}, Builder: func(newAction *BubbleJettonTransfer, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) newAction.success = true body := tx.decodedBody.Value.(abi.JettonNotifyMsgBody) newAction.amount = body.Amount newAction.payload = body.ForwardPayload.Value newAction.recipient = &tx.account return nil }, }, }
var StonfiV2PTONStrawReverse = Straw[BubbleJettonTransfer]{ CheckFuncs: []bubbleCheck{IsTx, HasInterface(abi.JettonWallet), HasOperation(abi.JettonTransferMsgOp)}, Builder: func(newAction *BubbleJettonTransfer, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) newAction.master, _ = tx.additionalInfo.JettonMaster(tx.account.Address) newAction.senderWallet = tx.account.Address newAction.sender = tx.inputFrom body := tx.decodedBody.Value.(abi.JettonTransferMsgBody) newAction.amount = body.Amount newAction.isWrappedTon = true newAction.payload = body.ForwardPayload.Value recipient, err := ton.AccountIDFromTlb(body.Destination) if err == nil { newAction.recipient = &Account{Address: *recipient} } return nil }, SingleChild: &Straw[BubbleJettonTransfer]{ CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.PtonTonTransferMsgOp)}, Builder: func(newAction *BubbleJettonTransfer, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) newAction.success = true newAction.recipient = &tx.account return nil }, }, }
var StrawAuctionBigGetgems = Straw[AuctionBidBubble]{ CheckFuncs: []bubbleCheck{IsTx, HasInterface(abi.NftAuctionV1), HasEmptyBody, AmountInterval(1, 1<<62)}, Builder: func(newAction *AuctionBidBubble, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) newAction.Auction = tx.account.Address newAction.Bidder = tx.inputFrom.Address newAction.Amount = tx.inputAmount newAction.Success = tx.success newAction.Type = GetGemsAuction if tx.additionalInfo != nil && tx.additionalInfo.NftSaleContract != nil { newAction.NftAddress = &tx.additionalInfo.NftSaleContract.Item } return nil }, }
var StrawAuctionBuyFragments = Straw[BubbleNftPurchase]{ CheckFuncs: []bubbleCheck{Is(AuctionBidBubble{})}, Builder: func(newAction *BubbleNftPurchase, bubble *Bubble) error { bid := bubble.Info.(AuctionBidBubble) newAction.Buyer = bid.Bidder newAction.Nft = *bid.NftAddress newAction.Price = bid.Amount newAction.AuctionType = bid.Type newAction.Success = bid.Success return nil }, SingleChild: &Straw[BubbleNftPurchase]{ CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.NftOwnershipAssignedMsgOp)}, Builder: func(newAction *BubbleNftPurchase, bubble *Bubble) error { seller := parseAccount(bubble.Info.(BubbleTx).decodedBody.Value.(abi.NftOwnershipAssignedMsgBody).PrevOwner) if seller != nil { newAction.Seller = seller.Address } return nil }, }, }
var StrawAuctionBuyGetgems = Straw[BubbleNftPurchase]{ CheckFuncs: []bubbleCheck{Is(AuctionBidBubble{})}, Builder: func(newAction *BubbleNftPurchase, bubble *Bubble) error { bid := bubble.Info.(AuctionBidBubble) newAction.Buyer = bid.Bidder newAction.Nft = *bid.NftAddress newAction.Price = bid.Amount newAction.AuctionType = bid.Type newAction.Success = bid.Success return nil }, SingleChild: &Straw[BubbleNftPurchase]{ CheckFuncs: []bubbleCheck{IsNftTransfer}, }, }
var StrawFindAuctionBidFragmentSimple = Straw[AuctionBidBubble]{ CheckFuncs: []bubbleCheck{IsTx, HasInterface(abi.Teleitem), HasEmptyBody, AmountInterval(1, 1<<62)}, Builder: func(newAction *AuctionBidBubble, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) newAction.Type = DnsTgAuction newAction.Amount = tx.inputAmount newAction.Bidder = tx.inputFrom.Address newAction.Success = tx.success newAction.Auction = tx.account.Address newAction.NftAddress = &tx.account.Address return nil }, }
var TgAuctionV1InitialBidStraw = Straw[AuctionBidBubble]{ CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.TelemintDeployMsgOp)}, Builder: func(newAction *AuctionBidBubble, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) body := tx.decodedBody.Value.(abi.TelemintDeployMsgBody) newAction.Type = DnsTgAuction newAction.Amount = tx.inputAmount newAction.Bidder = tx.inputFrom.Address newAction.Username = string(body.Msg.Username) return nil }, SingleChild: &Straw[AuctionBidBubble]{ CheckFuncs: []bubbleCheck{IsTx, HasOpcode(0x299a3e15)}, Builder: func(newAction *AuctionBidBubble, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) newAction.Success = tx.success newAction.Auction = tx.account.Address newAction.NftAddress = &tx.account.Address if tx.additionalInfo.EmulatedTeleitemNFT != nil { newAction.Nft = &core.NftItem{ Address: tx.account.Address, Index: tx.additionalInfo.EmulatedTeleitemNFT.Index, CollectionAddress: tx.additionalInfo.EmulatedTeleitemNFT.CollectionAddress, Verified: tx.additionalInfo.EmulatedTeleitemNFT.Verified, Transferable: false, Metadata: map[string]interface{}{ "name": newAction.Username, "image": fmt.Sprintf("https://nft.fragment.com/username/%v.webp", newAction.Username), }, } } return nil }, }, }
var UnSubscriptionStraw = Straw[BubbleUnSubscription]{ CheckFuncs: []bubbleCheck{IsTx}, Builder: func(newAction *BubbleUnSubscription, bubble *Bubble) error { newAction.Subscriber = bubble.Info.(BubbleTx).account return nil }, SingleChild: &Straw[BubbleUnSubscription]{ CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.WalletPluginDestructMsgOp)}, Builder: func(newAction *BubbleUnSubscription, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) newAction.Subscription = tx.account newAction.Success = tx.success return nil }, SingleChild: &Straw[BubbleUnSubscription]{ Optional: true, CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.WalletPluginDestructMsgOp)}, Builder: func(newAction *BubbleUnSubscription, bubble *Bubble) error { newAction.Beneficiary = bubble.Info.(BubbleTx).account return nil }, }, }, }
var WithdrawLiquidStake = Straw[BubbleWithdrawStake]{ CheckFuncs: []bubbleCheck{Is(BubbleWithdrawStakeRequest{})}, Builder: func(newAction *BubbleWithdrawStake, bubble *Bubble) error { request := bubble.Info.(BubbleWithdrawStakeRequest) newAction.Amount -= request.attachedAmount newAction.Pool = request.Pool newAction.Staker = request.Staker newAction.Implementation = request.Implementation return nil }, SingleChild: &Straw[BubbleWithdrawStake]{ CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.TonstakePoolWithdrawalMsgOp)}, Builder: func(newAction *BubbleWithdrawStake, bubble *Bubble) error { newAction.Amount += bubble.Info.(BubbleTx).inputAmount return nil }, }, }
var WithdrawStakeImmediatelyStraw = Straw[BubbleWithdrawStake]{ CheckFuncs: []bubbleCheck{Is(BubbleWithdrawStakeRequest{})}, Builder: func(newAction *BubbleWithdrawStake, bubble *Bubble) error { req := bubble.Info.(BubbleWithdrawStakeRequest) newAction.Pool = req.Pool newAction.Staker = req.Staker newAction.Amount = -req.attachedAmount newAction.Implementation = req.Implementation return nil }, SingleChild: &Straw[BubbleWithdrawStake]{ CheckFuncs: []bubbleCheck{IsTx, AmountInterval(int64(ton.OneTON), 1<<63-1)}, Builder: func(newAction *BubbleWithdrawStake, bubble *Bubble) error { newAction.Amount += bubble.Info.(BubbleTx).inputAmount return nil }, }, }
var WithdrawTFStakeRequestStraw = Straw[BubbleWithdrawStakeRequest]{ CheckFuncs: []bubbleCheck{IsTx, HasInterface(abi.TvPool), HasTextComment("w")}, Builder: func(newAction *BubbleWithdrawStakeRequest, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) newAction.Pool = tx.account.Address newAction.Staker = tx.inputFrom.Address newAction.Success = tx.success newAction.attachedAmount = tx.inputAmount newAction.Implementation = core.StakingImplementationTF return nil }, Children: []Straw[BubbleWithdrawStakeRequest]{ { Optional: true, CheckFuncs: []bubbleCheck{IsTx, AmountInterval(0, int64(ton.OneTON))}, }, }, }
var WtonMintStraw = Straw[BubbleJettonMint]{ CheckFuncs: []bubbleCheck{IsTx, HasOpcode(0x77a33521)}, Builder: func(newAction *BubbleJettonMint, bubble *Bubble) error { newAction.recipient = bubble.Info.(BubbleTx).account return nil }, Children: []Straw[BubbleJettonMint]{ { CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.JettonInternalTransferMsgOp)}, Builder: func(newAction *BubbleJettonMint, bubble *Bubble) error { tx := bubble.Info.(BubbleTx) body := tx.decodedBody.Value.(abi.JettonInternalTransferMsgBody) newAction.amount = body.Amount if tx.additionalInfo != nil { if master, ok := tx.additionalInfo.JettonMaster(tx.account.Address); ok { newAction.master = master } } newAction.recipientWallet = tx.account.Address newAction.success = tx.success return nil }, Children: []Straw[BubbleJettonMint]{ { CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.JettonNotifyMsgOp)}, Optional: true, }, { CheckFuncs: []bubbleCheck{Is(BubbleContractDeploy{})}, Optional: true, }, }, }, { CheckFuncs: []bubbleCheck{IsTx, HasOperation(abi.ExcessMsgOp)}, Optional: true, }, }, }
Functions ¶
func AmountInterval ¶
func AmountInterval(min, max int64) bubbleCheck
func HasEmptyBody ¶
func HasInterface ¶
func HasInterface(iface abi.ContractInterface) bubbleCheck
func HasOperation ¶
func HasTextComment ¶
func HasTextComment(comment string) bubbleCheck
func IsJettonReceiver ¶
func IsJettonReceiver(iface abi.ContractInterface) bubbleCheck
func IsJettonTransfer ¶
func IsNftTransfer ¶
func JettonTransferOpCode ¶
func JettonTransferOpCode(opCode uint32) bubbleCheck
func JettonTransferOperation ¶
func JettonTransferOperation(op abi.JettonOpName) bubbleCheck
func MergeAllBubbles ¶
Types ¶
type AccountValueFlow ¶
type AccountValueFlow struct {
Ton int64
Fees int64
Jettons map[tongo.AccountID]big.Int
NFTs [2]int // 0 - added, 1 - removed
}
AccountValueFlow contains a change of assets for a particular account.
type Action ¶
type Action struct {
TonTransfer *TonTransferAction `json:",omitempty"`
ExtraCurrencyTransfer *ExtraCurrencyTransferAction `json:",omitempty"`
SmartContractExec *SmartContractAction `json:",omitempty"`
GasRelay *GasRelayAction `json:",omitempty"`
NftItemTransfer *NftTransferAction `json:",omitempty"`
NftPurchase *NftPurchaseAction `json:",omitempty"`
JettonTransfer *JettonTransferAction `json:",omitempty"`
JettonMint *JettonMintAction `json:",omitempty"`
JettonBurn *JettonBurnAction `json:",omitempty"`
ContractDeploy *ContractDeployAction `json:",omitempty"`
Subscription *SubscriptionAction `json:",omitempty"`
UnSubscription *UnSubscriptionAction `json:",omitempty"`
AuctionBid *AuctionBidAction `json:",omitempty"`
ElectionsDepositStake *ElectionsDepositStakeAction `json:",omitempty"`
ElectionsRecoverStake *ElectionsRecoverStakeAction `json:",omitempty"`
DepositStake *DepositStakeAction `json:",omitempty"`
WithdrawStake *WithdrawStakeAction `json:",omitempty"`
WithdrawStakeRequest *WithdrawStakeRequestAction `json:",omitempty"`
JettonSwap *JettonSwapAction `json:",omitempty"`
DnsRenew *DnsRenewAction `json:",omitempty"`
Purchase *PurchaseAction `json:",omitempty"`
Success bool
Type ActionType
Error *string `json:",omitempty"`
BaseTransactions []ton.Bits256
}
type ActionType ¶
type ActionType string
const ( TonTransfer ActionType = "TonTransfer" ExtraCurrencyTransfer ActionType = "ExtraCurrencyTransfer" SmartContractExec ActionType = "SmartContractExec" GasRelay ActionType = "GasRelay" NftItemTransfer ActionType = "NftItemTransfer" NftPurchase ActionType = "NftPurchase" JettonTransfer ActionType = "JettonTransfer" JettonMint ActionType = "JettonMint" JettonBurn ActionType = "JettonBurn" ContractDeploy ActionType = "ContractDeploy" Subscription ActionType = "Subscribe" UnSubscription ActionType = "UnSubscribe" ElectionsDepositStake ActionType = "ElectionsDepositStake" ElectionsRecoverStake ActionType = "ElectionsRecoverStake" DepositStake ActionType = "DepositStake" WithdrawStake ActionType = "WithdrawStake" WithdrawStakeRequest ActionType = "WithdrawStakeRequest" JettonSwap ActionType = "JettonSwap" AuctionBid ActionType = "AuctionBid" DomainRenew ActionType = "DomainRenew" Purchase ActionType = "Purchase" Unknown ActionType = "Unknown" )
type ActionsList ¶
func EnrichWithIntentions ¶
func EnrichWithIntentions(trace *core.Trace, actions *ActionsList) *ActionsList
func FindActions ¶
FindActions finds known action patterns in the given trace and returns a list of actions.
type AuctionBidAction ¶
type AuctionBidAction struct {
Type NftAuctionType
Amount core.Price
Nft *core.NftItem
NftAddress *tongo.AccountID
Bidder tongo.AccountID
Auction tongo.AccountID
}
func (*AuctionBidAction) SubjectAccounts ¶
func (a *AuctionBidAction) SubjectAccounts() []tongo.AccountID
type AuctionBidBubble ¶
type AuctionBidBubble struct {
Type NftAuctionType
Amount int64
Nft *core.NftItem
NftAddress *tongo.AccountID
Bidder tongo.AccountID
Auction tongo.AccountID
PreviousBidder *tongo.AccountID //maybe don't requered
Username string
Success bool
}
func (AuctionBidBubble) ToAction ¶
func (a AuctionBidBubble) ToAction() *Action
type Bubble ¶
type Bubble struct {
Info actioner
Accounts []tongo.AccountID
Children []*Bubble
ValueFlow *ValueFlow
Transaction []ton.Bits256
}
Bubble represents a transaction in the beginning. But we can merge neighbour bubbles together if we find a known action pattern like an NFT Transfer or a SmartContractExecution in a trace.
func ProcessChildren ¶
type BubbleContractDeploy ¶
type BubbleContractDeploy struct {
Contract tongo.AccountID
// AccountInitInterfaces is a list of interfaces implemented by the stateInit.Code.
// This list can differ from the current list of interfaces.
// TODO: AccountInitInterfaces is an empty list in opentonapi, fix.
AccountInitInterfaces []abi.ContractInterface
Success bool
}
func (BubbleContractDeploy) ToAction ¶
func (b BubbleContractDeploy) ToAction() *Action
type BubbleDepositStake ¶
type BubbleDepositStake struct {
Staker tongo.AccountID
Amount int64
Success bool
Pool tongo.AccountID
Implementation core.StakingImplementation
}
func (BubbleDepositStake) ToAction ¶
func (ds BubbleDepositStake) ToAction() *Action
type BubbleDnsItemRenew ¶
type BubbleDnsItemRenew struct {
DnsRenewAction
Success bool
}
func (BubbleDnsItemRenew) ToAction ¶
func (b BubbleDnsItemRenew) ToAction() *Action
type BubbleElectionsDepositStake ¶
func (BubbleElectionsDepositStake) ToAction ¶
func (ds BubbleElectionsDepositStake) ToAction() *Action
type BubbleElectionsRecoverStake ¶
func (BubbleElectionsRecoverStake) ToAction ¶
func (b BubbleElectionsRecoverStake) ToAction() *Action
type BubbleInvoicePayment ¶
type BubbleInvoicePayment struct {
Sender, Recipient tongo.AccountID
InvoiceID uuid.UUID
Price core.Price
Success bool
}
func (BubbleInvoicePayment) ToAction ¶
func (b BubbleInvoicePayment) ToAction() (action *Action)
type BubbleJettonBurn ¶
type BubbleJettonBurn struct {
// contains filtered or unexported fields
}
func (BubbleJettonBurn) ToAction ¶
func (b BubbleJettonBurn) ToAction() (action *Action)
type BubbleJettonMint ¶
type BubbleJettonMint struct {
// contains filtered or unexported fields
}
func (BubbleJettonMint) ToAction ¶
func (b BubbleJettonMint) ToAction() (action *Action)
type BubbleJettonSwap ¶
type BubbleJettonSwap struct {
Dex Dex
UserWallet tongo.AccountID
Router tongo.AccountID
Out assetTransfer
In assetTransfer
Success bool
}
BubbleJettonSwap contains information about a jetton swap operation at a dex.
func (BubbleJettonSwap) ToAction ¶
func (b BubbleJettonSwap) ToAction() *Action
type BubbleJettonTransfer ¶
type BubbleJettonTransfer struct {
// contains filtered or unexported fields
}
func (BubbleJettonTransfer) ToAction ¶
func (b BubbleJettonTransfer) ToAction() (action *Action)
type BubbleNftPurchase ¶
type BubbleNftPurchase struct {
Success bool
Buyer tongo.AccountID
Seller tongo.AccountID
Nft tongo.AccountID
AuctionType NftAuctionType
Price int64
}
func (BubbleNftPurchase) ToAction ¶
func (b BubbleNftPurchase) ToAction() *Action
type BubbleNftTransfer ¶
type BubbleNftTransfer struct {
// contains filtered or unexported fields
}
func (BubbleNftTransfer) ToAction ¶
func (b BubbleNftTransfer) ToAction() (action *Action)
type BubbleSubscription ¶
type BubbleSubscription struct {
Subscription, Subscriber, Beneficiary Account
Amount int64
Success bool
First bool
}
func (BubbleSubscription) ToAction ¶
func (b BubbleSubscription) ToAction() (action *Action)
type BubbleUnSubscription ¶
func (BubbleUnSubscription) ToAction ¶
func (b BubbleUnSubscription) ToAction() (action *Action)
type BubbleWithdrawStake ¶
type BubbleWithdrawStake struct {
Staker tongo.AccountID
Amount int64
Pool tongo.AccountID
Implementation core.StakingImplementation
}
func (BubbleWithdrawStake) ToAction ¶
func (ds BubbleWithdrawStake) ToAction() *Action
type BubbleWithdrawStakeRequest ¶
type BubbleWithdrawStakeRequest struct {
Staker tongo.AccountID
Amount *int64
Success bool
Pool tongo.AccountID
Implementation core.StakingImplementation
// contains filtered or unexported fields
}
func (BubbleWithdrawStakeRequest) ToAction ¶
func (ds BubbleWithdrawStakeRequest) ToAction() *Action
type ContractDeployAction ¶
type ContractDeployAction struct {
Address tongo.AccountID
Interfaces []abi.ContractInterface
}
func (*ContractDeployAction) SubjectAccounts ¶
func (a *ContractDeployAction) SubjectAccounts() []tongo.AccountID
type ContractDeployment ¶
type ContractDeployment struct {
// contains filtered or unexported fields
}
ContractDeployment holds information about initialization of a contract.
type DepositStakeAction ¶
type DepositStakeAction struct {
Staker tongo.AccountID
Amount int64
Pool tongo.AccountID
Implementation core.StakingImplementation
}
func (*DepositStakeAction) SubjectAccounts ¶
func (a *DepositStakeAction) SubjectAccounts() []tongo.AccountID
type DnsRenewAction ¶
func (DnsRenewAction) SubjectAccounts ¶
func (a DnsRenewAction) SubjectAccounts() []ton.AccountID
type ElectionsDepositStakeAction ¶
type ElectionsDepositStakeAction struct {
Amount int64
Elector tongo.AccountID
Staker tongo.AccountID
}
func (*ElectionsDepositStakeAction) SubjectAccounts ¶
func (a *ElectionsDepositStakeAction) SubjectAccounts() []tongo.AccountID
type ElectionsRecoverStakeAction ¶
type ElectionsRecoverStakeAction struct {
Amount int64
Elector tongo.AccountID
Staker tongo.AccountID
}
func (*ElectionsRecoverStakeAction) SubjectAccounts ¶
func (a *ElectionsRecoverStakeAction) SubjectAccounts() []tongo.AccountID
type EncryptedComment ¶
type ExtraCurrencyTransferAction ¶
type ExtraCurrencyTransferAction struct {
CurrencyID int32
Amount tlb.VarUInteger32
Comment *string
EncryptedComment *EncryptedComment
Recipient tongo.AccountID
Sender tongo.AccountID
}
func (*ExtraCurrencyTransferAction) SubjectAccounts ¶
func (a *ExtraCurrencyTransferAction) SubjectAccounts() []tongo.AccountID
type GasRelayAction ¶
func (GasRelayAction) SubjectAccounts ¶
func (a GasRelayAction) SubjectAccounts() []ton.AccountID
type GasRelayBubble ¶
func (GasRelayBubble) ToAction ¶
func (b GasRelayBubble) ToAction() *Action
type JettonBurnAction ¶
type JettonBurnAction struct {
Jetton tongo.AccountID
Sender tongo.AccountID
SendersWallet tongo.AccountID
Amount tlb.VarUInteger16
}
func (*JettonBurnAction) SubjectAccounts ¶
func (a *JettonBurnAction) SubjectAccounts() []tongo.AccountID
type JettonMintAction ¶
type JettonMintAction struct {
Jetton tongo.AccountID
Recipient tongo.AccountID
RecipientsWallet tongo.AccountID
Amount tlb.VarUInteger16
}
func (*JettonMintAction) SubjectAccounts ¶
func (a *JettonMintAction) SubjectAccounts() []tongo.AccountID
type JettonSwapAction ¶
type JettonSwapAction struct {
Dex Dex
UserWallet tongo.AccountID
Router tongo.AccountID
In assetTransfer
Out assetTransfer
}
func (*JettonSwapAction) SubjectAccounts ¶
func (a *JettonSwapAction) SubjectAccounts() []tongo.AccountID
type JettonTransferAction ¶
type JettonTransferAction struct {
Comment *string
EncryptedComment *EncryptedComment
Jetton tongo.AccountID
Recipient *tongo.AccountID
Sender *tongo.AccountID
RecipientsWallet tongo.AccountID
SendersWallet tongo.AccountID
Amount tlb.VarUInteger16
Refund *Refund
// contains filtered or unexported fields
}
func (*JettonTransferAction) PayloadFromABI ¶
func (jta *JettonTransferAction) PayloadFromABI(payload abi.JettonPayload)
func (*JettonTransferAction) SubjectAccounts ¶
func (a *JettonTransferAction) SubjectAccounts() []tongo.AccountID
type NftAuctionType ¶
type NftAuctionType string
type NftPurchaseAction ¶
type NftPurchaseAction struct {
Nft tongo.AccountID
Buyer tongo.AccountID
Seller tongo.AccountID
AuctionType NftAuctionType
Price core.Price
}
func (*NftPurchaseAction) SubjectAccounts ¶
func (a *NftPurchaseAction) SubjectAccounts() []tongo.AccountID
type NftTransferAction ¶
type NftTransferAction struct {
Comment *string
EncryptedComment *EncryptedComment
Recipient *tongo.AccountID
Sender *tongo.AccountID
Nft tongo.AccountID
Refund *Refund
}
func (*NftTransferAction) SubjectAccounts ¶
func (a *NftTransferAction) SubjectAccounts() []tongo.AccountID
type Option ¶
type Option func(*Options)
func ForAccount ¶
func WithInformationSource ¶
func WithInformationSource(source core.InformationSource) Option
func WithStraws ¶
WithStraws provides functions to find actions in a trace.
type OutMessage ¶
type OutMessage struct {
// contains filtered or unexported fields
}
type PurchaseAction ¶
type PurchaseAction struct {
Source, Destination tongo.AccountID
InvoiceID uuid.UUID
Price core.Price
}
func (*PurchaseAction) SubjectAccounts ¶
func (a *PurchaseAction) SubjectAccounts() []tongo.AccountID
type Refund ¶
type Refund struct {
Type RefundType
Origin string
}
type RefundType ¶
type RefundType string
type SmartContractAction ¶
type SmartContractAction struct {
TonAttached int64
Executor tongo.AccountID
Contract tongo.AccountID
Operation string
Payload string
}
func (*SmartContractAction) SubjectAccounts ¶
func (a *SmartContractAction) SubjectAccounts() []tongo.AccountID
type Straw ¶
type Straw[newBubbleT actioner] struct {
CheckFuncs []bubbleCheck
Builder func(newAction *newBubbleT, bubble *Bubble) error //uses to convert old bubble to new Bubble.Info
ValueFlowUpdater func(newAction *newBubbleT, flow *ValueFlow)
SingleChild *Straw[newBubbleT]
Children []Straw[newBubbleT]
Optional bool
}
type SubscriptionAction ¶
type SubscriptionAction struct {
Subscription tongo.AccountID
Subscriber tongo.AccountID
Beneficiary tongo.AccountID
Amount int64
First bool
}
func (*SubscriptionAction) SubjectAccounts ¶
func (a *SubscriptionAction) SubjectAccounts() []tongo.AccountID
type TonTransferAction ¶
type TonTransferAction struct {
Amount int64
Comment *string
EncryptedComment *EncryptedComment
Recipient tongo.AccountID
Sender tongo.AccountID
Refund *Refund
}
func (*TonTransferAction) SubjectAccounts ¶
func (a *TonTransferAction) SubjectAccounts() []tongo.AccountID
type UnSubscriptionAction ¶
type UnSubscriptionAction struct {
Subscription tongo.AccountID
Subscriber tongo.AccountID
Beneficiary tongo.AccountID
}
func (*UnSubscriptionAction) SubjectAccounts ¶
func (a *UnSubscriptionAction) SubjectAccounts() []tongo.AccountID
type UniversalDedustStraw ¶
type UniversalDedustStraw struct{}
func (UniversalDedustStraw) Merge ¶
func (s UniversalDedustStraw) Merge(b *Bubble) bool
type ValueFlow ¶
type ValueFlow struct {
Accounts map[tongo.AccountID]*AccountValueFlow
}
ValueFlow contains a change of assets for each account involved in a trace.
func (*ValueFlow) AddJettons ¶
type WithdrawStakeAction ¶
type WithdrawStakeAction struct {
Staker tongo.AccountID
Amount int64
Pool tongo.AccountID
Implementation core.StakingImplementation
}
func (*WithdrawStakeAction) SubjectAccounts ¶
func (a *WithdrawStakeAction) SubjectAccounts() []tongo.AccountID
type WithdrawStakeRequestAction ¶
type WithdrawStakeRequestAction struct {
Staker tongo.AccountID
Amount *int64
Pool tongo.AccountID
Implementation core.StakingImplementation
}
func (*WithdrawStakeRequestAction) SubjectAccounts ¶
func (a *WithdrawStakeRequestAction) SubjectAccounts() []tongo.AccountID