github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/rpcclient/actor/doc_test.go (about) 1 package actor_test 2 3 import ( 4 "context" 5 "encoding/json" 6 "os" 7 8 "github.com/nspcc-dev/neo-go/pkg/core/transaction" 9 "github.com/nspcc-dev/neo-go/pkg/neorpc/result" 10 "github.com/nspcc-dev/neo-go/pkg/rpcclient" 11 "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" 12 "github.com/nspcc-dev/neo-go/pkg/rpcclient/neo" 13 "github.com/nspcc-dev/neo-go/pkg/rpcclient/policy" 14 sccontext "github.com/nspcc-dev/neo-go/pkg/smartcontract/context" 15 "github.com/nspcc-dev/neo-go/pkg/util" 16 "github.com/nspcc-dev/neo-go/pkg/vm/vmstate" 17 "github.com/nspcc-dev/neo-go/pkg/wallet" 18 ) 19 20 func ExampleActor() { 21 // No error checking done at all, intentionally. 22 w, _ := wallet.NewWalletFromFile("somewhere") 23 defer w.Close() 24 25 c, _ := rpcclient.New(context.Background(), "url", rpcclient.Options{}) 26 27 // Create a simple CalledByEntry-scoped actor (assuming there are accounts 28 // inside the wallet). 29 a, _ := actor.NewSimple(c, w.Accounts[0]) 30 31 customContract := util.Uint160{9, 8, 7} 32 // Actor has an Invoker inside, so we can perform test invocations, it will 33 // have a signer with the first wallet account and CalledByEntry scope. 34 res, _ := a.Call(customContract, "method", 1, 2, 3) 35 if res.State != vmstate.Halt.String() { 36 panic("failed") 37 } 38 // All of the side-effects in res can be analyzed. 39 40 // Now we want to send the same invocation in a transaction, but we already 41 // have the script and a proper system fee for it, therefore SendUncheckedRun 42 // can be used. 43 txid, vub, _ := a.SendUncheckedRun(res.Script, res.GasConsumed, nil, nil) 44 _ = txid 45 _ = vub 46 // You need to wait for it to persist and then check the on-chain result of it. 47 48 // Now we want to send some transaction, but give it a priority by increasing 49 // its network fee, this can be done with Tuned APIs. 50 txid, vub, _ = a.SendTunedCall(customContract, "method", nil, func(r *result.Invoke, t *transaction.Transaction) error { 51 // This code is run after the test-invocation done by *Call methods. 52 // Reuse the default function to check for HALT execution state. 53 err := actor.DefaultCheckerModifier(r, t) 54 if err != nil { 55 return err 56 } 57 // Some additional checks can be performed right here, but we only 58 // want to raise the network fee by ~20%. 59 t.NetworkFee += (t.NetworkFee / 5) 60 return nil 61 }, 1, 2, 3) 62 _ = txid 63 _ = vub 64 65 // Actor can be used for higher-level wrappers as well, if we want to interact with 66 // NEO then [neo] package can accept our Actor and allow to easily use NEO methods. 67 neoContract := neo.New(a) 68 balance, _ := neoContract.BalanceOf(a.Sender()) 69 _ = balance 70 71 // Now suppose the second wallet account is a committee account. We want to 72 // create and sign transactions for committee, but use the first account as 73 // a sender (because committee account has no GAS). We at the same time want 74 // to make all transactions using this actor high-priority ones, because 75 // committee can use this attribute. 76 77 // Get the default options to have CheckerModifier/Modifier set up correctly. 78 opts := actor.NewDefaultOptions() 79 // And override attributes. 80 opts.Attributes = []transaction.Attribute{{Type: transaction.HighPriority}} 81 82 // Create an Actor. 83 a, _ = actor.NewTuned(c, []actor.SignerAccount{{ 84 // Sender, regular account with None scope. 85 Signer: transaction.Signer{ 86 Account: w.Accounts[0].ScriptHash(), 87 Scopes: transaction.None, 88 }, 89 Account: w.Accounts[0], 90 }, { 91 // Commmitee. 92 Signer: transaction.Signer{ 93 Account: w.Accounts[1].ScriptHash(), 94 Scopes: transaction.CalledByEntry, 95 }, 96 Account: w.Accounts[1], 97 }}, opts) 98 99 // Use policy contract wrapper to simplify things. All changes in the 100 // Policy contract are made by the committee. 101 policyContract := policy.New(a) 102 103 // Create a transaction to set storage price, it'll be high-priority and have two 104 // signers from above. Committee is a multisignature account, so we can't sign/send 105 // it right away, w.Accounts[1] has only one public key. Therefore, we need to 106 // create a partially signed transaction and save it, then collect other signatures 107 // and send. 108 tx, _ := policyContract.SetStoragePriceUnsigned(10) 109 110 net := a.GetNetwork() 111 scCtx := sccontext.NewParameterContext(sccontext.TransactionType, net, tx) 112 sign := w.Accounts[0].SignHashable(net, tx) 113 _ = scCtx.AddSignature(w.Accounts[0].ScriptHash(), w.Accounts[0].Contract, w.Accounts[0].PublicKey(), sign) 114 115 sign = w.Accounts[1].SignHashable(net, tx) 116 _ = scCtx.AddSignature(w.Accounts[1].ScriptHash(), w.Accounts[1].Contract, w.Accounts[1].PublicKey(), sign) 117 118 data, _ := json.Marshal(scCtx) 119 _ = os.WriteFile("tx.json", data, 0644) 120 121 // Signature collection is out of scope, usually it's manual for cases like this. 122 }