From 026969ce35af4cc3811a0f48cfb655a02d1a1d2a Mon Sep 17 00:00:00 2001 From: Julien Cassis Date: Thu, 26 Nov 2020 20:06:13 -0500 Subject: [PATCH] cleaned up error handling --- .envrc | 1 + cmd/slnc/cmd/common.go | 3 -- cmd/slnc/cmd/get_account.go | 7 +-- cmd/slnc/cmd/get_balance.go | 3 +- cmd/slnc/cmd/get_confirmed_block.go | 18 ++----- cmd/slnc/cmd/get_program_accounts.go | 3 +- cmd/slnc/cmd/get_spl_token.go | 6 +-- cmd/slnc/cmd/get_transactions.go | 33 ++++++++----- cmd/slnc/cmd/logging.go | 17 ++----- cmd/slnc/cmd/request_airdrop.go | 12 +++-- cmd/slnc/cmd/root.go | 15 +++--- cmd/slnc/cmd/token_registry_get.go | 9 +++- cmd/slnc/cmd/token_registry_register.go | 62 ++++++++++++++++++------- cmd/slnc/cmd/vault_add.go | 24 +++++++--- cmd/slnc/cmd/vault_create.go | 28 +++++++---- programs/system/instructions.go | 2 +- rpc/client.go | 2 - rpc/client_test.go | 2 - transaction.go | 17 +++++-- transaction_test.go | 7 ++- 20 files changed, 162 insertions(+), 109 deletions(-) create mode 100644 .envrc diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..519199e --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +export SLNC_GLOBAL_INSECURE_VAULT_PASSPHRASE=secure diff --git a/cmd/slnc/cmd/common.go b/cmd/slnc/cmd/common.go index 962589a..729c43b 100644 --- a/cmd/slnc/cmd/common.go +++ b/cmd/slnc/cmd/common.go @@ -42,9 +42,6 @@ func getClient() *rpc.Client { } api.SetHeader(headerArray[0], headerArray[1]) } - - api.Debug = viper.GetBool("global-debug") - return api } diff --git a/cmd/slnc/cmd/get_account.go b/cmd/slnc/cmd/get_account.go index b928185..00f302a 100644 --- a/cmd/slnc/cmd/get_account.go +++ b/cmd/slnc/cmd/get_account.go @@ -38,9 +38,10 @@ var getAccountCmd = &cobra.Command{ } acct := resp.Value - - data, err := json.MarshalIndent(acct, "", " ") - errorCheck("json marshal", err) + var data []byte + if data, err = json.MarshalIndent(acct, "", " "); err != nil { + return fmt.Errorf("unable to marshall account information: %w", err) + } fmt.Println(string(data)) diff --git a/cmd/slnc/cmd/get_balance.go b/cmd/slnc/cmd/get_balance.go index d4ffb4f..9d27bb1 100644 --- a/cmd/slnc/cmd/get_balance.go +++ b/cmd/slnc/cmd/get_balance.go @@ -16,7 +16,6 @@ package cmd import ( "context" - "errors" "fmt" "github.com/spf13/cobra" @@ -36,7 +35,7 @@ var getBalanceCmd = &cobra.Command{ } if resp.Value == 0 { - errorCheck("not found", errors.New("account not found")) + return fmt.Errorf("account not found") } fmt.Println(resp.Value, "lamports") diff --git a/cmd/slnc/cmd/get_confirmed_block.go b/cmd/slnc/cmd/get_confirmed_block.go index 1d36e75..0fc293e 100644 --- a/cmd/slnc/cmd/get_confirmed_block.go +++ b/cmd/slnc/cmd/get_confirmed_block.go @@ -27,12 +27,14 @@ var getConfirmedBlockCmd = &cobra.Command{ Use: "confirmed-block {block_num}", Short: "Retrieve a confirmed block, with all of its transactions", Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, args []string) (err error) { client := getClient() ctx := context.Background() - slot, err := strconv.ParseInt(args[0], 10, 64) - errorCheck("parsing slot number in first argument", err) + var slot int64 + if slot, err = strconv.ParseInt(args[0], 10, 64); err != nil { + return fmt.Errorf("unable to parse provided slot number %q: %w", args[0], err) + } resp, err := client.GetConfirmedBlock(ctx, uint64(slot), "") if err != nil { @@ -42,16 +44,6 @@ var getConfirmedBlockCmd = &cobra.Command{ cnt, _ := json.MarshalIndent(resp, "", " ") fmt.Println(string(cnt)) - // for idx, trx := range resp.Transactions { - // unpacked, err := solana.TransactionFromData(trx.Transaction) - // if err != nil { - // return err - // } - - // cnt, _ := json.MarshalIndent(unpacked, "", " ") - // fmt.Println(idx, string(cnt)) - // } - return nil }, } diff --git a/cmd/slnc/cmd/get_program_accounts.go b/cmd/slnc/cmd/get_program_accounts.go index e410229..58967f5 100644 --- a/cmd/slnc/cmd/get_program_accounts.go +++ b/cmd/slnc/cmd/get_program_accounts.go @@ -17,7 +17,6 @@ package cmd import ( "context" "encoding/json" - "errors" "fmt" "github.com/dfuse-io/solana-go" @@ -39,7 +38,7 @@ var getProgramAccountsCmd = &cobra.Command{ } if resp == nil { - errorCheck("not found", errors.New("program account not found")) + return fmt.Errorf("program account not found") } for _, keyedAcct := range resp { diff --git a/cmd/slnc/cmd/get_spl_token.go b/cmd/slnc/cmd/get_spl_token.go index fa30e52..0ebb623 100644 --- a/cmd/slnc/cmd/get_spl_token.go +++ b/cmd/slnc/cmd/get_spl_token.go @@ -15,8 +15,6 @@ package cmd import ( - "context" - "errors" "fmt" "log" "os" @@ -35,7 +33,7 @@ var getSPLTokenCmd = &cobra.Command{ Args: cobra.ExactArgs(0), RunE: func(cmd *cobra.Command, args []string) error { client := getClient() - ctx := context.Background() + ctx := cmd.Context() resp, err := client.GetProgramAccounts( ctx, @@ -53,7 +51,7 @@ var getSPLTokenCmd = &cobra.Command{ } if resp == nil { - errorCheck("not found", errors.New("program account not found")) + return fmt.Errorf("program account not found") } for _, keyedAcct := range resp { diff --git a/cmd/slnc/cmd/get_transactions.go b/cmd/slnc/cmd/get_transactions.go index 1305a8f..fb0252d 100644 --- a/cmd/slnc/cmd/get_transactions.go +++ b/cmd/slnc/cmd/get_transactions.go @@ -39,15 +39,18 @@ var getTransactionsCmd = &cobra.Command{ address := args[0] pubKey, err := solana.PublicKeyFromBase58(address) - errorCheck("public key", err) + if err != nil { + return fmt.Errorf("invalid account address %q: %w", address, err) + } csList, err := client.GetConfirmedSignaturesForAddress2(ctx, pubKey, &rpc.GetConfirmedSignaturesForAddress2Opts{ Limit: 1, Before: "", Until: "", }) - - errorCheck("getting confirm transaction:", err) + if err != nil { + return fmt.Errorf("unable to retrieve confirmed transaction signatures for account: %w", err) + } for _, cs := range csList { fmt.Println("-----------------------------------------------------------------------------------------------") @@ -60,19 +63,22 @@ var getTransactionsCmd = &cobra.Command{ fmt.Println(cs.Memo) ct, err := client.GetConfirmedTransaction(ctx, cs.Signature) - errorCheck("confirm transaction", err) + if err != nil { + return fmt.Errorf("unable to get confirmed transaction with signature %q: %w", cs.Signature, err) + } + if ct.Meta.Err != nil { - fmt.Println("ERROR:", ct.Meta.Err) - // for k, _ := range ct.Meta.Err + return fmt.Errorf("unable to get confirmed transaction with signature %q: %s", cs.Signature, ct.Meta.Err) } fmt.Print("\nInstructions:\n-------------\n\n") for _, i := range ct.Transaction.Message.Instructions { - //Missing Initial account instruction ?????? - id, err := ct.Transaction.ResolveProgramIDIndex(i.ProgramIDIndex) - errorCheck("resolving programID", err) + if err != nil { + return fmt.Errorf("unable to resolve program ID: %w", err) + } + decoder := solana.InstructionDecoderRegistry[id.String()] if decoder == nil { fmt.Println("raw instruction:") @@ -88,9 +94,14 @@ var getTransactionsCmd = &cobra.Command{ } decoded, err := decoder(ct.Transaction.AccountMetaList(), &i) - errorCheck("bin decode", err) + if err != nil { + return fmt.Errorf("unable to decode instruction: %w", err) + } + err = text.NewEncoder(os.Stdout).Encode(decoded, nil) - errorCheck("textEncoding", err) + if err != nil { + return fmt.Errorf("unable to text encoder instruction: %w", err) + } } text.EncoderColorCyan.Print("\n\nEnd of transaction\n\n") } diff --git a/cmd/slnc/cmd/logging.go b/cmd/slnc/cmd/logging.go index 506791d..9a66f45 100644 --- a/cmd/slnc/cmd/logging.go +++ b/cmd/slnc/cmd/logging.go @@ -15,7 +15,6 @@ package cmd import ( - "fmt" "os" "strings" @@ -32,19 +31,9 @@ func init() { logging.Register("github.com/dfuse-io/solana-go/cmd/slnc/cmd", &zlog) } -func SetupLogger(debug bool) { - fmt.Println("setting logger with debug:", debug) - if debug { - zlog, err := zap.NewDevelopment() - fmt.Println("setting logger1") - if err == nil { - fmt.Println("setting logger2") - logging.Set(zlog) - } - // Hijack standard Golang `log` and redirect it to our common logger - zap.RedirectStdLogAt(zlog, zap.DebugLevel) - - } +func SetupLogger() { + commonLogger := createLogger("cli", 1, zap.FatalLevel) + logging.Set(commonLogger) // Fine-grain customization // diff --git a/cmd/slnc/cmd/request_airdrop.go b/cmd/slnc/cmd/request_airdrop.go index 3e49bb5..387b9a2 100644 --- a/cmd/slnc/cmd/request_airdrop.go +++ b/cmd/slnc/cmd/request_airdrop.go @@ -26,14 +26,16 @@ import ( var requestCmd = &cobra.Command{ Use: "request-airdrop {address} {lamport}", - Short: "request lamport airdrop for an account", + Short: "Request lamport airdrop for an account", Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error { client := getClient() address, err := solana.PublicKeyFromBase58(args[0]) - errorCheck("invalid token address", err) + if err != nil { + return fmt.Errorf("invalid account address %q: %w", args[0], err) + } lamport, err := strconv.Atoi(args[1]) if err != nil { @@ -41,9 +43,11 @@ var requestCmd = &cobra.Command{ } airDrop, err := client.RequestAirdrop(context.Background(), &address, uint64(lamport), rpc.CommitmentMax) - errorCheck("air drop", err) - fmt.Println("air drop hash:", airDrop) + if err != nil { + return fmt.Errorf("airdrop request failed: %w", err) + } + fmt.Println("Air drop succeeded, transaction hash:", airDrop) return nil }, } diff --git a/cmd/slnc/cmd/root.go b/cmd/slnc/cmd/root.go index 505a75c..cd66df6 100644 --- a/cmd/slnc/cmd/root.go +++ b/cmd/slnc/cmd/root.go @@ -46,19 +46,17 @@ func Execute() { func init() { cobra.OnInitialize(initConfig) - - RootCmd.PersistentFlags().BoolP("debug", "", false, "Enables verbose API debug messages") + // Not implemnted + //RootCmd.PersistentFlags().BoolP("debug", "", false, "Enables verbose API debug messages") RootCmd.PersistentFlags().StringP("vault-file", "", "./solana-vault.json", "Wallet file that contains encrypted key material") RootCmd.PersistentFlags().StringP("rpc-url", "u", defaultRPCURL, "API endpoint of eos.io blockchain node") RootCmd.PersistentFlags().StringSliceP("http-header", "H", []string{}, "HTTP header to add to JSON-RPC requests") RootCmd.PersistentFlags().StringP("kms-gcp-keypath", "", "", "Path to the cryptoKeys within a keyRing on GCP") - // RootCmd.PersistentFlags().StringP("write-transaction", "", "", "Do not broadcast the transaction produced, but write it in json to the given filename instead.") - // RootCmd.PersistentFlags().StringP("offline-head-block", "", "", "Provide a recent block ID (long-form hex) for TaPoS. Use all --offline options to sign transactions offline.") - // RootCmd.PersistentFlags().StringP("offline-chain-id", "", "", "Chain ID to sign transaction with. Use all --offline- options to sign transactions offline.") - // RootCmd.PersistentFlags().StringSliceP("offline-sign-key", "", []string{}, "Public key to use to sign transaction. Must be in your vault or wallet. Use all --offline- options to sign transactions offline.") - // RootCmd.PersistentFlags().BoolP("skip-sign", "", false, "Do not sign the transaction. Use with --write-transaction.") - SetupLogger(viper.GetBool("global-debug")) + RootCmd.PersistentPreRunE = func(cmd *cobra.Command, args []string) error { + SetupLogger() + return nil + } } func initConfig() { @@ -66,7 +64,6 @@ func initConfig() { viper.AutomaticEnv() replacer := strings.NewReplacer("-", "_") viper.SetEnvKeyReplacer(replacer) - recurseViperCommands(RootCmd, nil) } diff --git a/cmd/slnc/cmd/token_registry_get.go b/cmd/slnc/cmd/token_registry_get.go index 08b4f6b..8a1aae8 100644 --- a/cmd/slnc/cmd/token_registry_get.go +++ b/cmd/slnc/cmd/token_registry_get.go @@ -35,7 +35,9 @@ var tokenRegistryGetCmd = &cobra.Command{ address := args[0] pubKey, err := solana.PublicKeyFromBase58(address) - errorCheck("public key", err) + if err != nil { + return fmt.Errorf("invalid mint address %q: %w", address, err) + } t, err := tokenregistry.GetTokenRegistryEntry(cmd.Context(), client, pubKey) if err != nil { @@ -47,7 +49,10 @@ var tokenRegistryGetCmd = &cobra.Command{ } err = text.NewEncoder(os.Stdout).Encode(t, nil) - errorCheck("textEncoding", err) + if err != nil { + return fmt.Errorf("unable to text encode token registry entry: %w", err) + } + return nil }, } diff --git a/cmd/slnc/cmd/token_registry_register.go b/cmd/slnc/cmd/token_registry_register.go index e53a002..53c547b 100644 --- a/cmd/slnc/cmd/token_registry_register.go +++ b/cmd/slnc/cmd/token_registry_register.go @@ -18,6 +18,8 @@ import ( "context" "fmt" + "github.com/dfuse-io/solana-go/rpc" + "github.com/spf13/viper" "github.com/dfuse-io/solana-go" @@ -27,22 +29,31 @@ import ( ) var tokenRegistryRegisterCmd = &cobra.Command{ - Use: "register {token} {name} {symbol} {logo}", + Use: "register {token-address} {name} {symbol} {logo}", Short: "register meta data for a token", Args: cobra.ExactArgs(4), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, args []string) (err error) { vault := mustGetWallet() client := getClient() - tokenAddress, err := solana.PublicKeyFromBase58(args[0]) - errorCheck("invalid token address", err) + var tokenAddress solana.PublicKey + if tokenAddress, err = solana.PublicKeyFromBase58(args[0]); err != nil { + return fmt.Errorf("invalid token address %q: %w", args[0], err) + } - logo, err := tokenregistry.LogoFromString(args[1]) - errorCheck("invalid logo", err) - name, err := tokenregistry.NameFromString(args[2]) - errorCheck("invalid name", err) - symbol, err := tokenregistry.SymbolFromString(args[3]) - errorCheck("invalid symbol", err) + var logo tokenregistry.Logo + var name tokenregistry.Name + var symbol tokenregistry.Symbol + + if logo, err = tokenregistry.LogoFromString(args[1]); err != nil { + return fmt.Errorf("invalid logo %q: %w", args[1], err) + } + if name, err = tokenregistry.NameFromString(args[2]); err != nil { + return fmt.Errorf("invalid name %q: %w", args[2], err) + } + if symbol, err = tokenregistry.SymbolFromString(args[3]); err != nil { + return fmt.Errorf("invalid symbol %q: %w", args[3], err) + } pkeyStr := viper.GetString("token-registry-register-cmd-registrar") if pkeyStr == "" { @@ -50,7 +61,9 @@ var tokenRegistryRegisterCmd = &cobra.Command{ } registrarPubKey, err := solana.PublicKeyFromBase58(pkeyStr) - errorCheck(fmt.Sprintf("invalid registrar key %q", pkeyStr), err) + if err != nil { + return fmt.Errorf("invalid registrar key %q: %w", pkeyStr, err) + } found := false for _, privateKey := range vault.KeyBag { @@ -62,22 +75,29 @@ var tokenRegistryRegisterCmd = &cobra.Command{ return fmt.Errorf("registrar key must be present in the vault to register a token") } - fmt.Println(registrarPubKey.String()) + blockHashResult, err := client.GetRecentBlockhash(context.Background(), rpc.CommitmentMax) + if err != nil { + return fmt.Errorf("unable retrieve recent block hash: %w", err) + } tokenMetaAccount := solana.NewAccount() lamport, err := client.GetMinimumBalanceForRentExemption(context.Background(), tokenregistry.TOKEN_META_SIZE) - errorCheck("get minimum balance for rent exemption ", err) + if err != nil { + return fmt.Errorf("unable to retrieve lapoint rent: %w", err) + } tokenRegistryProgramID := tokenregistry.ProgramID() createAccountInstruction := system.NewCreateAccountInstruction(uint64(lamport), tokenregistry.TOKEN_META_SIZE, tokenRegistryProgramID, registrarPubKey, tokenMetaAccount.PublicKey()) registerTokenInstruction := tokenregistry.NewRegisterTokenInstruction(logo, name, symbol, tokenMetaAccount.PublicKey(), registrarPubKey, tokenAddress) - trx, err := solana.TransactionWithInstructions([]solana.TransactionInstruction{createAccountInstruction, registerTokenInstruction}, &solana.Options{ + trx, err := solana.TransactionWithInstructions([]solana.TransactionInstruction{createAccountInstruction, registerTokenInstruction}, blockHashResult.Value.Blockhash, &solana.Options{ Payer: registrarPubKey, }) - errorCheck("unable to craft transaction", err) + if err != nil { + return fmt.Errorf("unable to craft transaction: %w", err) + } _, err = trx.Sign(func(key solana.PublicKey) *solana.PrivateKey { for _, k := range vault.KeyBag { @@ -87,12 +107,18 @@ var tokenRegistryRegisterCmd = &cobra.Command{ } return nil }) - - errorCheck("unable to sign transaction", err) + if err != nil { + return fmt.Errorf("unable to sign transaction: %w", err) + } trxHash, err := client.SendTransaction(cmd.Context(), trx) + if err != nil { + return fmt.Errorf("unable to send transaction: %w", err) + } - fmt.Println("sent transaction hash:", trxHash, " error:", err) + fmt.Printf("Token Register successfully, with transaction hash: %s\n", trxHash) + fmt.Printf(" Mint Address Registerd: %s\n", tokenAddress.String()) + fmt.Printf(" Token Registry Meta Address: %s\n", tokenMetaAccount.PublicKey().String()) return nil }, } diff --git a/cmd/slnc/cmd/vault_add.go b/cmd/slnc/cmd/vault_add.go index 147f575..72474de 100644 --- a/cmd/slnc/cmd/vault_add.go +++ b/cmd/slnc/cmd/vault_add.go @@ -34,18 +34,26 @@ var vaultAddCmd = &cobra.Command{ fmt.Println("Loading existing vault from file:", walletFile) v, err := vault.NewVaultFromWalletFile(walletFile) - errorCheck("loading vault from file", err) + if err != nil { + fmt.Errorf("unable to load vault file: %w", err) + } boxer, err := vault.SecretBoxerForType(v.SecretBoxWrap, viper.GetString("global-kms-gcp-keypath")) - errorCheck("missing parameters", err) + if err != nil { + fmt.Errorf("unable to intiate boxer: %w", err) + } err = v.Open(boxer) - errorCheck("opening vault", err) + if err != nil { + fmt.Errorf("unable to open vault: %w", err) + } v.PrintPublicKeys() privateKeys, err := capturePrivateKeys() - errorCheck("entering private keys", err) + if err != nil { + fmt.Errorf("failed to enter private keys: %w", err) + } var newKeys []solana.PublicKey for _, privateKey := range privateKeys { @@ -54,10 +62,14 @@ var vaultAddCmd = &cobra.Command{ } err = v.Seal(boxer) - errorCheck("sealing vault", err) + if err != nil { + fmt.Errorf("failed to seal vault: %w", err) + } err = v.WriteToFile(walletFile) - errorCheck("writing vault file", err) + if err != nil { + fmt.Errorf("failed to write vault file: %w", err) + } vaultWrittenReport(walletFile, newKeys, len(v.KeyBag)) }, diff --git a/cmd/slnc/cmd/vault_create.go b/cmd/slnc/cmd/vault_create.go index c7e88a6..6d67093 100644 --- a/cmd/slnc/cmd/vault_create.go +++ b/cmd/slnc/cmd/vault_create.go @@ -46,7 +46,7 @@ You can create a Google Cloud Platform KMS-wrapped vault with: cmd vault create --keys=2 --vault-type=kms-gcp --kms-gcp-keypath projects/.../locations/.../keyRings/.../cryptoKeys/name You can then use this vault for the different cmd operations.`, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) (err error) { walletFile := viper.GetString("global-vault-file") if _, err := os.Stat(walletFile); err == nil { @@ -59,7 +59,7 @@ You can then use this vault for the different cmd operations.`, kmsGCPKeypath := viper.GetString("global-kms-gcp-keypath") if wrapType == "kms-gcp" && kmsGCPKeypath == "" { - errorCheck("missing parameter", fmt.Errorf("--kms-gcp-keypath is required with --vault-type=kms-gcp")) + return fmt.Errorf("missing parameter: --kms-gcp-keypath is required with --vault-type=kms-gcp") } v := vault.NewVault() @@ -70,7 +70,9 @@ You can then use this vault for the different cmd operations.`, doImport := viper.GetBool("vault-create-cmd-import") if doImport { privateKeys, err := capturePrivateKeys() - errorCheck("entering private key", err) + if err != nil { + return fmt.Errorf("failed enterign private key: %w", err) + } for _, privateKey := range privateKeys { v.AddPrivateKey(privateKey) @@ -83,12 +85,14 @@ You can then use this vault for the different cmd operations.`, numKeys := viper.GetInt("vault-create-cmd-keys") if numKeys == 0 { - errorCheck("specify either --keys or --import", fmt.Errorf("create a vault with 0 keys?")) + return fmt.Errorf("specify either --keys or --import: create a vault with 0 keys?") } for i := 0; i < numKeys; i++ { pubKey, err := v.NewKeyPair() - errorCheck("creating new keypair", err) + if err != nil { + return fmt.Errorf("unable ot create new keypair: %w", err) + } newKeys = append(newKeys, pubKey) } @@ -109,7 +113,9 @@ You can then use this vault for the different cmd operations.`, boxer = vault.NewPassphraseBoxer(envVal) } else { password, err := cli.GetEncryptPassphrase() - errorCheck("password input", err) + if err != nil { + return fmt.Errorf("failed to get password input: %w", err) + } boxer = vault.NewPassphraseBoxer(password) } @@ -119,10 +125,16 @@ You can then use this vault for the different cmd operations.`, os.Exit(1) } - errorCheck("sealing vault", v.Seal(boxer)) - errorCheck("writing wallet file", v.WriteToFile(walletFile)) + if err = v.Seal(boxer); err != nil { + return fmt.Errorf("failed to seal the vault: %w", err) + } + + if err = v.WriteToFile(walletFile); err != nil { + return fmt.Errorf("failed to write vault file: %w", err) + } vaultWrittenReport(walletFile, newKeys, len(v.KeyBag)) + return nil }, } diff --git a/programs/system/instructions.go b/programs/system/instructions.go index e2566fe..e924d13 100644 --- a/programs/system/instructions.go +++ b/programs/system/instructions.go @@ -64,7 +64,7 @@ func NewCreateAccountInstruction(lamports uint64, space uint64, owner, from, to Owner: owner, Accounts: &CreateAccountAccounts{ From: &solana.AccountMeta{PublicKey: from, IsSigner: true, IsWritable: true}, - New: &solana.AccountMeta{PublicKey: to, IsSigner: true, IsWritable: true}, + New: &solana.AccountMeta{PublicKey: to, IsSigner: false, IsWritable: true}, }, }, }, diff --git a/rpc/client.go b/rpc/client.go index f1fdaa6..c92bf6c 100644 --- a/rpc/client.go +++ b/rpc/client.go @@ -33,8 +33,6 @@ type Client struct { rpcURL string rpcClient jsonrpc.RPCClient headers http.Header - - Debug bool } func NewClient(rpcURL string) *Client { diff --git a/rpc/client_test.go b/rpc/client_test.go index 6604c13..fa2b4b4 100644 --- a/rpc/client_test.go +++ b/rpc/client_test.go @@ -57,7 +57,6 @@ func TestClient_GetConfirmedSignaturesForAddress2(t *testing.T) { func TestClient_GetConfirmedTransaction(t *testing.T) { zlog, _ = zap.NewDevelopment() c := NewClient("http://api.mainnet-beta.solana.com:80/rpc") - c.Debug = true signature := "53hoZ98EsCMA6L63GWM65M3Bd3WqA4LxD8bcJkbKoKWhbJFqX9M1WZ4fSjt8bYyZn21NwNnV2A25zirBni9Qk6LR" trx, err := c.GetConfirmedTransaction(context.Background(), signature) require.NoError(t, err) @@ -79,7 +78,6 @@ func TestClient_GetConfirmedTransaction(t *testing.T) { func TestClient_getMinimumBalanceForRentExemption(t *testing.T) { zlog, _ = zap.NewDevelopment() c := NewClient("http://api.mainnet-beta.solana.com:80/rpc") - c.Debug = true lamport, err := c.GetMinimumBalanceForRentExemption(context.Background(), 100) require.NoError(t, err) require.Equal(t, 1586880, lamport) diff --git a/transaction.go b/transaction.go index 72ce352..0dbf5a3 100644 --- a/transaction.go +++ b/transaction.go @@ -20,7 +20,7 @@ type Options struct { Payer PublicKey } -func TransactionWithInstructions(instructions []TransactionInstruction, opt *Options) (*Transaction, error) { +func TransactionWithInstructions(instructions []TransactionInstruction, blockHash PublicKey, opt *Options) (*Transaction, error) { if len(instructions) == 0 { return nil, fmt.Errorf("requires at-least one instruction to create a transaction") } @@ -106,12 +106,16 @@ func TransactionWithInstructions(instructions []TransactionInstruction, opt *Opt } message := Message{ - AccountKeys: nil, - RecentBlockhash: PublicKey{}, - Instructions: nil, + RecentBlockhash: blockHash, } accountKeyIndex := map[string]uint8{} for idx, acc := range finalAccounts { + + zlog.Debug("transaction account", + zap.Int("account_index", idx), + zap.Stringer("account_pub_key", acc.PublicKey), + ) + message.AccountKeys = append(message.AccountKeys, acc.PublicKey) accountKeyIndex[acc.PublicKey.String()] = uint8(idx) if acc.IsSigner { @@ -126,6 +130,11 @@ func TransactionWithInstructions(instructions []TransactionInstruction, opt *Opt message.Header.NumReadonlyUnsignedAccounts++ } } + zlog.Debug("message header compiled", + zap.Uint8("num_required_signatures", message.Header.NumRequiredSignatures), + zap.Uint8("num_readonly_signed_accounts", message.Header.NumReadonlySignedAccounts), + zap.Uint8("num_readonly_unsigned_accounts", message.Header.NumReadonlyUnsignedAccounts), + ) for trxIdx, instruction := range instructions { accounts = instruction.Accounts() diff --git a/transaction_test.go b/transaction_test.go index 1563b6c..68d6b8f 100644 --- a/transaction_test.go +++ b/transaction_test.go @@ -47,7 +47,10 @@ func TestTransactionWithInstructions(t *testing.T) { }, } - trx, err := TransactionWithInstructions(instructions, nil) + blockhash, err := PublicKeyFromBase58("A9QnpgfhCkmiBSjgBuWk76Wo3HxzxvDopUq9x6UUMmjn") + require.NoError(t, err) + + trx, err := TransactionWithInstructions(instructions, blockhash, nil) require.NoError(t, err) assert.Equal(t, trx.Message.Header, MessageHeader{ @@ -56,6 +59,8 @@ func TestTransactionWithInstructions(t *testing.T) { NumReadonlyUnsignedAccounts: 3, }) + assert.Equal(t, trx.Message.RecentBlockhash, blockhash) + assert.Equal(t, trx.Message.AccountKeys, []PublicKey{ MustPublicKeyFromBase58("A9QnpgfhCkmiBSjgBuWk76Wo3HxzxvDopUq9x6UUMmjn"), MustPublicKeyFromBase58("9hFtYBYmBJCVguRYs9pBTWKYAFoKfjYR7zBPpEkVsmD"),