diff --git a/buxclient_test.go b/buxclient_test.go index 4666d120..7fca5c97 100644 --- a/buxclient_test.go +++ b/buxclient_test.go @@ -9,11 +9,12 @@ import ( "testing" buxmodels "github.com/BuxOrg/bux-models" - "github.com/BuxOrg/go-buxclient/transports" "github.com/bitcoinschema/go-bitcoin/v2" "github.com/libsv/go-bt/v2" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/BuxOrg/go-buxclient/transports" ) const ( @@ -21,7 +22,6 @@ const ( adminKeyXpub = "xprv9s21ZrQH143K4Z8JnrQ7XsYxzKbFNsAEPyHMaMU2fbMtoY1YmsJLFo3XBkg2m7e9UJLS6xvd2HjZ5WN9fQbMSGU7uXEE2pksvbQYCXswLB5" destinationJSON = `{"id":"90d10acb85f37dd009238fe7ec61a1411725825c82099bd8432fcb47ad8326ce","xpub_id":"9fe44728bf16a2dde3748f72cc65ea661f3bf18653b320d31eafcab37cf7fb36","locking_script":"76a9140e0eb4911d79e9b7683f268964f595b66fa3604588ac","type":"pubkeyhash","chain":0,"num":245,"address":"12HL5RyEy3Rt6SCwxgpiFSTigem1Pzbq22","metadata":{"test":"test value"}}}` draftTxJSON = `{"created_at":"2022-02-09T16:28:39.000639Z","updated_at":"0001-01-01T00:00:00Z","deleted_at":null,"id":"fe6fe12c25b81106b7332d58fe87dab7bc6e56c8c21ca45b4de05f673f3f653c","hex":"010000000141e3be4d5a3f25e11157bfdd100e7c3497b9be2b80b57eb55e5376b075e7dc5d0200000000ffffffff02e8030000000000001976a9147ff514e6ae3deb46e6644caac5cdd0bf2388906588ac170e0000000000001976a9143dbdb346aaf1c3dc501a2f8c186c3d3e8a87764588ac00000000","xpub_id":"9fe44728bf16a2dde3748f72cc65ea661f3bf18653b320d31eafcab37cf7fb36","expires_at":"2022-02-09T16:29:08.991801Z","metadata":{"testkey":"test-value"},"configuration":{"change_destinations":[{"created_at":"2022-02-09T16:28:38.997313Z","updated_at":"0001-01-01T00:00:00Z","deleted_at":null,"id":"252e8a915a5f05effab827a887e261a2416a76f3d3aada946a70a575c0bb76a7","xpub_id":"9fe44728bf16a2dde3748f72cc65ea661f3bf18653b320d31eafcab37cf7fb36","locking_script":"76a9143dbdb346aaf1c3dc501a2f8c186c3d3e8a87764588ac","type":"pubkeyhash","chain":1,"num":100,"address":"16dTUJwi7qT3JqzAUMcDHaVV3sB4fH85Ep","draft_id":"fe6fe12c25b81106b7332d58fe87dab7bc6e56c8c21ca45b4de05f673f3f653c"}],"change_destinations_strategy":"","change_minimum_satoshis":0,"change_number_of_destinations":0,"change_satoshis":3607,"expires_in":0,"fee":97,"fee_unit":{"satoshis":1,"bytes":2},"from_utxos":null,"inputs":[{"created_at":"2022-01-28T13:45:02.352Z","updated_at":"2022-02-09T16:28:38.993207Z","deleted_at":null,"id":"efe383eea1a6f7925afb2621b69ea9ba6bd0623e8d61827bad994f8be85161fc","transaction_id":"5ddce775b076535eb57eb5802bbeb997347c0e10ddbf5711e1253f5a4dbee341","xpub_id":"9fe44728bf16a2dde3748f72cc65ea661f3bf18653b320d31eafcab37cf7fb36","output_index":2,"satoshis":4704,"script_pub_key":"76a914c746bf0f295375cbea4a5ef25b36c84ff9801bac88ac","type":"pubkeyhash","draft_id":"fe6fe12c25b81106b7332d58fe87dab7bc6e56c8c21ca45b4de05f673f3f653c","reserved_at":"2022-02-09T16:28:38.993205Z","spending_tx_id":null,"destination":{"created_at":"2022-01-28T13:45:02.324Z","updated_at":"0001-01-01T00:00:00Z","metadata":{"client_id":"8","run":90,"run_id":"3108aa426fc7102488bb0ffd","xbench":"destination for testing"},"deleted_at":null,"id":"b8bfa56e37c90f1b25df2e571f727cfec80dd17c5d1845c4b93e21034f7f6a0b","xpub_id":"9fe44728bf16a2dde3748f72cc65ea661f3bf18653b320d31eafcab37cf7fb36","locking_script":"76a914c746bf0f295375cbea4a5ef25b36c84ff9801bac88ac","type":"pubkeyhash","chain":0,"num":212,"address":"1KAgDiUasnC7roCjQZM1XLJUpq4BYHjdp6","draft_id":""}}],"miner":"","outputs":[{"satoshis":1000,"scripts":[{"address":"1CfaQw9udYNPccssFJFZ94DN8MqNZm9nGt","satoshis":1000,"script":"76a9147ff514e6ae3deb46e6644caac5cdd0bf2388906588ac","script_type":"pubkeyhash"}],"to":"1CfaQw9udYNPccssFJFZ94DN8MqNZm9nGt","op_return":null},{"satoshis":3607,"scripts":[{"address":"16dTUJwi7qT3JqzAUMcDHaVV3sB4fH85Ep","satoshis":3607,"script":"76a9143dbdb346aaf1c3dc501a2f8c186c3d3e8a87764588ac","script_type":""}],"to":"16dTUJwi7qT3JqzAUMcDHaVV3sB4fH85Ep","op_return":null}],"send_all_to":{},"sync":null},"status":"draft"}` - requestTypeGraphQL = "graphql" requestTypeHTTP = "http" serverURL = "https://example.com/" testAddress = "1CfaQw9udYNPccssFJFZ94DN8MqNZm9nGt" @@ -32,6 +32,7 @@ const ( xPrivString = "xprv9s21ZrQH143K3N6qVJQAu4EP51qMcyrKYJLkLgmYXgz58xmVxVLSsbx2DfJUtjcnXK8NdvkHMKfmmg5AJT2nqqRWUrjSHX29qEJwBgBPkJQ" xPubID = "9fe44728bf16a2dde3748f72cc65ea661f3bf18653b320d31eafcab37cf7fb36" xpubJSON = `{"data":{"xpub":{"id":"0092de4d2aafa59a71a1f90342c138e1c4f19cd1b10e2d17422b34a1d06733e0"}}}` + xPubJSON = `{"id":"0092de4d2aafa59a71a1f90342c138e1c4f19cd1b10e2d17422b34a1d06733e0"}` xPubString = "xpub661MyMwAqRbcFrBJbKwBGCB7d3fr2SaAuXGM95BA62X41m6eW2ehRQGW4xLi9wkEXUGnQZYxVVj4PxXnyrLk7jdqvBAs1Qq9gf6ykMvjR7J" ) @@ -192,101 +193,77 @@ func TestSetSignRequest(t *testing.T) { // TestDraftTransaction will test the DraftTransaction method func TestDraftTransaction(t *testing.T) { - transportHandlers := []testTransportHandler{{ + transportHandler := testTransportHandler{ Type: requestTypeHTTP, Path: "/transaction", Result: draftTxJSON, ClientURL: serverURL, Client: WithHTTPClient, - }, { - Type: requestTypeGraphQL, - Path: "/graphql", - Result: `{"data":{"new_transaction":` + draftTxJSON + `}}`, - ClientURL: serverURL + `graphql`, - Client: WithGraphQLClient, - }} - - for _, transportHandler := range transportHandlers { - t.Run("draft transaction "+transportHandler.Type, func(t *testing.T) { - client := getTestBuxClient(transportHandler, false) - config := &buxmodels.TransactionConfig{ - Outputs: []*buxmodels.TransactionOutput{{ - Satoshis: 1000, - To: testAddress, - }}, - } - metadata := &buxmodels.Metadata{ - "test-key": "test-value", - } - - draft, err := client.DraftTransaction(context.Background(), config, metadata) - assert.NoError(t, err) - checkDraftTransactionOutput(t, draft) - }) } + + t.Run("draft transaction", func(t *testing.T) { + client := getTestBuxClient(transportHandler, false) + config := &buxmodels.TransactionConfig{ + Outputs: []*buxmodels.TransactionOutput{{ + Satoshis: 1000, + To: testAddress, + }}, + } + metadata := &buxmodels.Metadata{ + "test-key": "test-value", + } + + draft, err := client.DraftTransaction(context.Background(), config, metadata) + assert.NoError(t, err) + checkDraftTransactionOutput(t, draft) + }) } // TestNewXpub will test the NewXpub method func TestNewXpub(t *testing.T) { - transportHandlers := []testTransportHandler{{ + transportHandler := testTransportHandler{ Type: requestTypeHTTP, Path: "/xpub", Result: xpubJSON, ClientURL: serverURL, Client: WithHTTPClient, - }, { - Type: requestTypeGraphQL, - Path: "/graphql", - Result: `{"data":{"xpub":` + xpubJSON + `}}`, - ClientURL: serverURL + `graphql`, - Client: WithGraphQLClient, - }} - - for _, transportHandler := range transportHandlers { - t.Run("NewXpub "+transportHandler.Type, func(t *testing.T) { - client := getTestBuxClient(transportHandler, true) - metadata := &buxmodels.Metadata{ - "test-key": "test-value", - } - err := client.NewXpub(context.Background(), xPubString, metadata) - assert.NoError(t, err) - }) } + + t.Run("NewXpub", func(t *testing.T) { + client := getTestBuxClient(transportHandler, true) + metadata := &buxmodels.Metadata{ + "test-key": "test-value", + } + err := client.NewXpub(context.Background(), xPubString, metadata) + assert.NoError(t, err) + }) } // TestDraftToRecipients will test the DraftToRecipients method func TestDraftToRecipients(t *testing.T) { - transportHandlers := []testTransportHandler{{ + transportHandler := testTransportHandler{ Type: requestTypeHTTP, Path: "/transaction", Result: draftTxJSON, ClientURL: serverURL, Client: WithHTTPClient, - }, { - Type: requestTypeGraphQL, - Path: "/graphql", - Result: `{"data":{"new_transaction":` + draftTxJSON + `}}`, - ClientURL: serverURL + `graphql`, - Client: WithGraphQLClient, - }} - - for _, transportHandler := range transportHandlers { - t.Run("DraftToRecipients "+transportHandler.Type, func(t *testing.T) { - client := getTestBuxClient(transportHandler, false) - - recipients := []*transports.Recipients{{ - Satoshis: 1000, - To: testAddress, - }} - metadata := &buxmodels.Metadata{ - "test-key": "test-value", - } - - draft, err := client.DraftToRecipients(context.Background(), recipients, metadata) - assert.NoError(t, err) - checkDraftTransactionOutput(t, draft) - }) } + + t.Run("DraftToRecipients "+transportHandler.Type, func(t *testing.T) { + client := getTestBuxClient(transportHandler, false) + + recipients := []*transports.Recipients{{ + Satoshis: 1000, + To: testAddress, + }} + metadata := &buxmodels.Metadata{ + "test-key": "test-value", + } + + draft, err := client.DraftToRecipients(context.Background(), recipients, metadata) + assert.NoError(t, err) + checkDraftTransactionOutput(t, draft) + }) } func checkDraftTransactionOutput(t *testing.T, draft *buxmodels.DraftTransaction) { @@ -300,149 +277,117 @@ func checkDraftTransactionOutput(t *testing.T, draft *buxmodels.DraftTransaction // TestNewDestination will test the NewDestination method func TestNewDestination(t *testing.T) { - transportHandlers := []testTransportHandler{{ + transportHandler := testTransportHandler{ Type: requestTypeHTTP, Path: "/destination", Result: destinationJSON, ClientURL: serverURL, Client: WithHTTPClient, - }, { - Type: requestTypeGraphQL, - Path: "/graphql", - Result: `{"data":{"destination":` + destinationJSON + `}}`, - ClientURL: serverURL + `graphql`, - Client: WithGraphQLClient, - }} - - for _, transportHandler := range transportHandlers { - t.Run("new destination "+transportHandler.Type, func(t *testing.T) { - client := getTestBuxClient(transportHandler, false) - - destination, err := client.NewDestination(context.Background(), nil) - assert.NoError(t, err) - assert.IsType(t, buxmodels.Destination{}, *destination) - assert.Equal(t, "90d10acb85f37dd009238fe7ec61a1411725825c82099bd8432fcb47ad8326ce", destination.ID) - assert.Equal(t, xPubID, destination.XpubID) - assert.Equal(t, "76a9140e0eb4911d79e9b7683f268964f595b66fa3604588ac", destination.LockingScript) - assert.Equal(t, uint32(0), destination.Chain) - assert.Equal(t, uint32(245), destination.Num) - assert.Equal(t, "12HL5RyEy3Rt6SCwxgpiFSTigem1Pzbq22", destination.Address) - }) } + + t.Run("new destination"+transportHandler.Type, func(t *testing.T) { + client := getTestBuxClient(transportHandler, false) + + destination, err := client.NewDestination(context.Background(), nil) + assert.NoError(t, err) + assert.IsType(t, buxmodels.Destination{}, *destination) + assert.Equal(t, "90d10acb85f37dd009238fe7ec61a1411725825c82099bd8432fcb47ad8326ce", destination.ID) + assert.Equal(t, xPubID, destination.XpubID) + assert.Equal(t, "76a9140e0eb4911d79e9b7683f268964f595b66fa3604588ac", destination.LockingScript) + assert.Equal(t, uint32(0), destination.Chain) + assert.Equal(t, uint32(245), destination.Num) + assert.Equal(t, "12HL5RyEy3Rt6SCwxgpiFSTigem1Pzbq22", destination.Address) + }) } // TestGetTransaction will test the GetTransaction method func TestGetTransaction(t *testing.T) { - transportHandlers := []testTransportHandler{{ + transportHandler := testTransportHandler{ Type: requestTypeHTTP, Path: "/transaction", Result: transactionJSON, ClientURL: serverURL, Client: WithHTTPClient, - }, { - Type: requestTypeGraphQL, - Path: "/graphql", - Result: `{"data":{"transaction":` + transactionJSON + `}}`, - ClientURL: serverURL + `graphql`, - Client: WithGraphQLClient, - }} - - for _, transportHandler := range transportHandlers { - t.Run("get transaction "+transportHandler.Type, func(t *testing.T) { - client := getTestBuxClient(transportHandler, false) - - transaction, err := client.GetTransaction(context.Background(), txID) - assert.NoError(t, err) - assert.IsType(t, buxmodels.Transaction{}, *transaction) - assert.Equal(t, txID, transaction.ID) - assert.Equal(t, uint64(354), transaction.Fee) - assert.Equal(t, uint32(4), transaction.NumberOfInputs) - assert.Equal(t, uint32(4), transaction.NumberOfOutputs) - assert.Equal(t, uint64(6955), transaction.TotalValue) - }) } + + t.Run("get transaction", func(t *testing.T) { + client := getTestBuxClient(transportHandler, false) + + transaction, err := client.GetTransaction(context.Background(), txID) + assert.NoError(t, err) + assert.IsType(t, buxmodels.Transaction{}, *transaction) + assert.Equal(t, txID, transaction.ID) + assert.Equal(t, uint64(354), transaction.Fee) + assert.Equal(t, uint32(4), transaction.NumberOfInputs) + assert.Equal(t, uint32(4), transaction.NumberOfOutputs) + assert.Equal(t, uint64(6955), transaction.TotalValue) + }) } // TestGetTransactions will test the GetTransactions method func TestGetTransactions(t *testing.T) { - transportHandlers := []testTransportHandler{{ + transportHandler := testTransportHandler{ Type: requestTypeHTTP, Path: "/transaction/search", Result: transactionsJSON, ClientURL: serverURL, Client: WithHTTPClient, - }, { - Type: requestTypeGraphQL, - Path: "/graphql", - Result: `{"data":{"transactions":` + transactionsJSON + `}}`, - ClientURL: serverURL + `graphql`, - Client: WithGraphQLClient, - }} - - for _, transportHandler := range transportHandlers { - t.Run("get transactions "+transportHandler.Type, func(t *testing.T) { - client := getTestBuxClient(transportHandler, false) - - conditions := map[string]interface{}{ - "fee": map[string]interface{}{ - "$lt": 100, - }, - "total_value": map[string]interface{}{ - "$lt": 740, - }, - } - metadata := &buxmodels.Metadata{ - "run_id": "3108aa426fc7102488bb0ffd", - } - transactions, err := client.GetTransactions(context.Background(), conditions, metadata, &transports.QueryParams{}) - assert.NoError(t, err) - assert.IsType(t, []*buxmodels.Transaction{}, transactions) - assert.Len(t, transactions, 2) - assert.Equal(t, "caae6e799210dfea7591e3d55455437eb7e1091bb01463ae1e7ddf9e29c75eda", transactions[0].ID) - assert.Equal(t, uint64(97), transactions[0].Fee) - assert.Equal(t, uint64(733), transactions[0].TotalValue) - assert.Equal(t, "5f4fd2be162769852e8bd1362bb8d815a89e137707b4985249876a7f0ebbb071", transactions[1].ID) - assert.Equal(t, uint64(97), transactions[1].Fee) - assert.Equal(t, uint64(423), transactions[1].TotalValue) - }) } + + t.Run("get transactions "+transportHandler.Type, func(t *testing.T) { + client := getTestBuxClient(transportHandler, false) + + conditions := map[string]interface{}{ + "fee": map[string]interface{}{ + "$lt": 100, + }, + "total_value": map[string]interface{}{ + "$lt": 740, + }, + } + metadata := &buxmodels.Metadata{ + "run_id": "3108aa426fc7102488bb0ffd", + } + transactions, err := client.GetTransactions(context.Background(), conditions, metadata, &transports.QueryParams{}) + assert.NoError(t, err) + assert.IsType(t, []*buxmodels.Transaction{}, transactions) + assert.Len(t, transactions, 2) + assert.Equal(t, "caae6e799210dfea7591e3d55455437eb7e1091bb01463ae1e7ddf9e29c75eda", transactions[0].ID) + assert.Equal(t, uint64(97), transactions[0].Fee) + assert.Equal(t, uint64(733), transactions[0].TotalValue) + assert.Equal(t, "5f4fd2be162769852e8bd1362bb8d815a89e137707b4985249876a7f0ebbb071", transactions[1].ID) + assert.Equal(t, uint64(97), transactions[1].Fee) + assert.Equal(t, uint64(423), transactions[1].TotalValue) + }) } // TestRecordTransaction will test the RecordTransaction method func TestRecordTransaction(t *testing.T) { - transportHandlers := []testTransportHandler{{ + transportHandler := testTransportHandler{ Type: requestTypeHTTP, Path: "/transaction/record", Result: transactionJSON, ClientURL: serverURL, Client: WithHTTPClient, - }, { - Type: requestTypeGraphQL, - Path: "/graphql", - Result: `{"data":{"transaction":` + transactionJSON + `}}`, - ClientURL: serverURL + `graphql`, - Client: WithGraphQLClient, - }} - - for _, transportHandler := range transportHandlers { - t.Run("record transaction "+transportHandler.Type, func(t *testing.T) { - client := getTestBuxClient(transportHandler, false) - - hex := "" - metadata := &buxmodels.Metadata{ - "test-key": "test-value", - } - transaction, err := client.RecordTransaction(context.Background(), hex, "", metadata) - assert.NoError(t, err) - assert.IsType(t, buxmodels.Transaction{}, *transaction) - assert.Equal(t, txID, transaction.ID) - }) } + + t.Run("record transaction"+transportHandler.Type, func(t *testing.T) { + client := getTestBuxClient(transportHandler, false) + + hex := "" + metadata := &buxmodels.Metadata{ + "test-key": "test-value", + } + transaction, err := client.RecordTransaction(context.Background(), hex, "", metadata) + assert.NoError(t, err) + assert.IsType(t, buxmodels.Transaction{}, *transaction) + assert.Equal(t, txID, transaction.ID) + }) } // TestSendToRecipients will test the SendToRecipients method func TestSendToRecipients(t *testing.T) { - transportHandlers := []testTransportHandler{{ + transportHandler := testTransportHandler{ Type: requestTypeHTTP, Queries: []*testTransportHandlerRequest{{ Path: "/transaction", @@ -459,43 +404,26 @@ func TestSendToRecipients(t *testing.T) { }}, ClientURL: serverURL, Client: WithHTTPClient, - }, { - Type: requestTypeGraphQL, - Queries: []*testTransportHandlerRequest{{ - Path: "/graphql", - Result: func(w http.ResponseWriter, req *http.Request) { - result := `{"data":{"transaction":` + transactionJSON + `}}` - if req.ContentLength > 1000 { - result = `{"data":{"new_transaction":` + draftTxJSON + `}}` - } - w.Header().Set("Content-Type", "application/json") - mustWrite(w, result) - }, - }}, - ClientURL: serverURL + `graphql`, - Client: WithGraphQLClient, - }} + } - for _, transportHandler := range transportHandlers { - t.Run("send to recipients "+transportHandler.Type, func(t *testing.T) { - client := getTestBuxClient(transportHandler, false) + t.Run("send to recipients", func(t *testing.T) { + client := getTestBuxClient(transportHandler, false) - recipients := []*transports.Recipients{{ - To: testAddress, - Satoshis: 1234, - }, { - To: testAddress2, - Satoshis: 4321, - }} - metadata := &buxmodels.Metadata{ - "test-key": "test-value", - } - transaction, err := client.SendToRecipients(context.Background(), recipients, metadata) - require.NoError(t, err) - assert.IsType(t, buxmodels.Transaction{}, *transaction) - assert.Equal(t, txID, transaction.ID) - }) - } + recipients := []*transports.Recipients{{ + To: testAddress, + Satoshis: 1234, + }, { + To: testAddress2, + Satoshis: 4321, + }} + metadata := &buxmodels.Metadata{ + "test-key": "test-value", + } + transaction, err := client.SendToRecipients(context.Background(), recipients, metadata) + require.NoError(t, err) + assert.IsType(t, buxmodels.Transaction{}, *transaction) + assert.Equal(t, txID, transaction.ID) + }) } // TestFinalizeTransaction will test the FinalizeTransaction method @@ -540,12 +468,12 @@ func TestGetTransport(t *testing.T) { t.Run("client GetTransport", func(t *testing.T) { client, _ := New( WithXPriv(xPrivString), - WithGraphQL(serverURL), + WithHTTP(serverURL), WithAdminKey(xPrivString), WithSignRequest(false), ) transport := client.GetTransport() - assert.IsType(t, &transports.TransportGraphQL{}, *transport) + assert.IsType(t, &transports.TransportHTTP{}, *transport) }) } @@ -635,29 +563,6 @@ func TestAuthenticationWithOnlyAccessKey(t *testing.T) { t.Log(err) } }) - - t.Run("graphqlClient."+test.caseTitle, func(t *testing.T) { - transportHandler := testTransportHandler{ - Type: requestTypeGraphQL, - Queries: []*testTransportHandlerRequest{{ - Path: "/graphql", - Result: func(w http.ResponseWriter, req *http.Request) { - assertAuthHeaders(t, req) - w.Header().Set("Content-Type", "application/json") - mustWrite(w, `{"data":{}}`) - }, - }}, - ClientURL: serverURL + `graphql`, - Client: WithGraphQLClient, - } - - client := getTestBuxClientWithOpts(transportHandler, WithAccessKey(accessKeyString)) - - _, err := test.clientMethod(client) - if err != nil { - t.Log(err) - } - }) } } diff --git a/client_options.go b/client_options.go index cd19fc58..11ef18ea 100644 --- a/client_options.go +++ b/client_options.go @@ -42,15 +42,6 @@ func WithHTTP(serverURL string) ClientOps { } } -// WithGraphQL will overwrite the default client with a custom client -func WithGraphQL(serverURL string) ClientOps { - return func(c *BuxClient) { - if c != nil { - c.transportOptions = append(c.transportOptions, transports.WithGraphQL(serverURL)) - } - } -} - // WithHTTPClient will overwrite the default client with a custom client func WithHTTPClient(serverURL string, httpClient *http.Client) ClientOps { return func(c *BuxClient) { @@ -60,15 +51,6 @@ func WithHTTPClient(serverURL string, httpClient *http.Client) ClientOps { } } -// WithGraphQLClient will overwrite the default client with a custom client -func WithGraphQLClient(serverURL string, httpClient *http.Client) ClientOps { - return func(c *BuxClient) { - if c != nil { - c.transportOptions = append(c.transportOptions, transports.WithGraphQLClient(serverURL, httpClient)) - } - } -} - // WithAdminKey will set the admin key for admin requests func WithAdminKey(adminKey string) ClientOps { return func(c *BuxClient) { diff --git a/examples/graphql/graphql.go b/examples/graphql/graphql.go deleted file mode 100644 index 41ba0f77..00000000 --- a/examples/graphql/graphql.go +++ /dev/null @@ -1,19 +0,0 @@ -package main - -import ( - "github.com/BuxOrg/go-buxclient" - "github.com/BuxOrg/go-buxclient/xpriv" -) - -func main() { - - // Generate keys - keys, _ := xpriv.Generate() - - // Create a client - _, _ = buxclient.New( - buxclient.WithXPriv(keys.XPriv()), - buxclient.WithGraphQL("localhost:3001"), - buxclient.WithSignRequest(true), - ) -} diff --git a/go.mod b/go.mod index 55adfdc8..34c0868c 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,6 @@ require ( github.com/bitcoinschema/go-bitcoin/v2 v2.0.5 github.com/libsv/go-bk v0.1.6 github.com/libsv/go-bt/v2 v2.2.5 - github.com/machinebox/graphql v0.2.2 github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.8.4 ) @@ -15,7 +14,6 @@ require ( require ( github.com/bitcoinsv/bsvd v0.0.0-20190609155523-4c29707f7173 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/matryer/is v1.4.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect golang.org/x/crypto v0.17.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 547a465d..2dcf05e1 100644 --- a/go.sum +++ b/go.sum @@ -14,10 +14,6 @@ github.com/libsv/go-bk v0.1.6 h1:c9CiT5+64HRDbzxPl1v/oiFmbvWZTuUYqywCf+MBs/c= github.com/libsv/go-bk v0.1.6/go.mod h1:khJboDoH18FPUaZlzRFKzlVN84d4YfdmlDtdX4LAjQA= github.com/libsv/go-bt/v2 v2.2.5 h1:VoggBLMRW9NYoFujqe5bSYKqnw5y+fYfufgERSoubog= github.com/libsv/go-bt/v2 v2.2.5/go.mod h1:cV45+jDlPOLfhJLfpLmpQoWzrIvVth9Ao2ZO1f6CcqU= -github.com/machinebox/graphql v0.2.2 h1:dWKpJligYKhYKO5A2gvNhkJdQMNZeChZYyBbrZkBZfo= -github.com/machinebox/graphql v0.2.2/go.mod h1:F+kbVMHuwrQ5tYgU9JXlnskM8nOaFxCAEolaQybkjWA= -github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ= -github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= diff --git a/transports/client_options.go b/transports/client_options.go index d9c67955..73c6f275 100644 --- a/transports/client_options.go +++ b/transports/client_options.go @@ -34,23 +34,6 @@ func WithAccessKey(accessKey *bec.PrivateKey) ClientOps { } } -// WithGraphQL will overwrite the default client with a custom client -func WithGraphQL(serverURL string) ClientOps { - return func(c *Client) { - if c != nil { - c.transport = NewTransportService(&TransportGraphQL{ - server: serverURL, - signRequest: c.signRequest, - adminXPriv: c.adminXPriv, - httpClient: &http.Client{}, - xPriv: c.xPriv, - xPub: c.xPub, - accessKey: c.accessKey, - }) - } - } -} - // WithHTTP will overwrite the default client with a custom client func WithHTTP(serverURL string) ClientOps { return func(c *Client) { @@ -68,23 +51,6 @@ func WithHTTP(serverURL string) ClientOps { } } -// WithGraphQLClient will overwrite the default client with a custom client -func WithGraphQLClient(serverURL string, httpClient *http.Client) ClientOps { - return func(c *Client) { - if c != nil { - c.transport = NewTransportService(&TransportGraphQL{ - server: serverURL, - signRequest: c.signRequest, - adminXPriv: c.adminXPriv, - httpClient: httpClient, - xPriv: c.xPriv, - xPub: c.xPub, - accessKey: c.accessKey, - }) - } - } -} - // WithHTTPClient will overwrite the default client with a custom client func WithHTTPClient(serverURL string, httpClient *http.Client) ClientOps { return func(c *Client) { diff --git a/transports/config.go b/transports/config.go index 16414b83..b0e1f2f0 100644 --- a/transports/config.go +++ b/transports/config.go @@ -2,7 +2,7 @@ package transports import buxmodels "github.com/BuxOrg/bux-models" -// TransportType the type of transport being used (http or graphql) +// TransportType the type of transport being used ('http' for usage or 'mock' for testing) type TransportType string // BuxUserAgent the bux user agent sent to the bux server @@ -15,9 +15,6 @@ const ( // BuxTransportHTTP uses the http transport for all bux server actions BuxTransportHTTP TransportType = "http" - // BuxTransportGraphQL uses the graphql transport for all bux server actions - BuxTransportGraphQL TransportType = "graphql" - // BuxTransportMock uses the mock transport for all bux server actions BuxTransportMock TransportType = "mock" ) diff --git a/transports/graphql.go b/transports/graphql.go deleted file mode 100644 index 9c70224e..00000000 --- a/transports/graphql.go +++ /dev/null @@ -1,1114 +0,0 @@ -package transports - -import ( - "context" - "encoding/hex" - "encoding/json" - "net/http" - - buxmodels "github.com/BuxOrg/bux-models" - buxerrors "github.com/BuxOrg/bux-models/bux-errors" - "github.com/libsv/go-bk/bec" - "github.com/libsv/go-bk/bip32" - "github.com/machinebox/graphql" -) - -// graphQlService is the interface for GraphQL -type graphQlService interface { - Run(ctx context.Context, req *graphql.Request, resp interface{}) error -} - -// TransportGraphQL is the graphql struct -type TransportGraphQL struct { - accessKey *bec.PrivateKey - adminXPriv *bip32.ExtendedKey - client graphQlService - httpClient *http.Client - server string - signRequest bool - xPriv *bip32.ExtendedKey - xPub *bip32.ExtendedKey -} - -// XPubData is the xpub data -type XPubData struct { - XPub *buxmodels.Xpub `json:"xpub"` -} - -// XPubMetadataData is the xpub data for the metadata mutation -type XPubMetadataData struct { - XPub *buxmodels.Xpub `json:"xpub_metadata"` -} - -// AccessKeyData is the access key data -type AccessKeyData struct { - AccessKey *buxmodels.AccessKey `json:"access_key"` -} - -// AccessKeysData is a slice of access key data -type AccessKeysData struct { - AccessKeys []*buxmodels.AccessKey `json:"access_keys"` -} - -// DestinationData is the destination data -type DestinationData struct { - Destination *buxmodels.Destination `json:"destination"` -} - -// DestinationMetadataData is the destination data for the metadata mutation -type DestinationMetadataData struct { - Destination *buxmodels.Destination `json:"destination_metadata"` -} - -// DestinationsData is a slice of destination data -type DestinationsData struct { - Destinations []*buxmodels.Destination `json:"destinations"` -} - -// DraftTransactionData is a draft transaction -type DraftTransactionData struct { - NewTransaction *buxmodels.DraftTransaction `json:"new_transaction"` -} - -// TransactionData is a transaction -type TransactionData struct { - Transaction *buxmodels.Transaction `json:"transaction"` -} - -// TransactionMetadataData is a transaction for the metadata mutation -type TransactionMetadataData struct { - Transaction *buxmodels.Transaction `json:"transaction_metadata"` -} - -// TransactionsData is a slice of transactions -type TransactionsData struct { - Transactions []*buxmodels.Transaction `json:"transactions"` -} - -// NewTransactionData is a transaction -type NewTransactionData struct { - Transaction *buxmodels.Transaction `json:"transaction"` -} - -// UtxoData is a utxo -type UtxoData struct { - Utxo *buxmodels.Utxo `json:"utxo"` -} - -// UtxosData is a slice of utxos -type UtxosData struct { - Utxos []*buxmodels.Utxo `json:"utxos"` -} - -// Init will initialize -func (g *TransportGraphQL) Init() error { - g.client = graphql.NewClient(g.server, graphql.WithHTTPClient(g.httpClient)) - return nil -} - -// SetAdminKey set the admin key -func (g *TransportGraphQL) SetAdminKey(adminKey *bip32.ExtendedKey) { - g.adminXPriv = adminKey -} - -// SetSignRequest turn the signing of the HTTP request on or off -func (g *TransportGraphQL) SetSignRequest(signRequest bool) { - g.signRequest = signRequest -} - -// IsSignRequest return whether to sign all requests -func (g *TransportGraphQL) IsSignRequest() bool { - return g.signRequest -} - -// NewPaymail will register a new paymail -func (g *TransportGraphQL) NewPaymail(_ context.Context, _, _, _, _ string, _ *buxmodels.Metadata) ResponseError { - // TODO: Implement this - return nil -} - -// DeletePaymail will delete a paymail address -func (g *TransportGraphQL) DeletePaymail(_ context.Context, _ string) ResponseError { - // TODO: Implement this - return nil -} - -// GetXpub will get an xPub -func (g *TransportGraphQL) GetXpub(_ context.Context, _ string) (*buxmodels.Xpub, ResponseError) { - // TODO: Implement this - return nil, nil -} - -// GetXPub will get information about the current xPub -func (g *TransportGraphQL) GetXPub(ctx context.Context) (*buxmodels.Xpub, ResponseError) { - reqBody := ` - query { - xpub { - id - current_balance - next_internal_num - next_external_num - metadata - created_at - updated_at - deleted_at - } - }` - - var respData XPubData - if err := g.doGraphQLQuery(ctx, reqBody, nil, &respData); err != nil { - return nil, err - } - - return respData.XPub, nil -} - -// UpdateXPubMetadata update the metadata of the logged in xpub -func (g *TransportGraphQL) UpdateXPubMetadata(ctx context.Context, metadata *buxmodels.Metadata) (*buxmodels.Xpub, ResponseError) { - reqBody := ` - mutation ($metadata: Metadata!) { - xpub_metadata ( - metadata: $metadata - ) { - id - current_balance - next_internal_num - next_external_num - metadata - created_at - updated_at - deleted_at - } - }` - variables := map[string]interface{}{ - FieldMetadata: processMetadata(metadata), - } - - var respData XPubMetadataData - if err := g.doGraphQLQuery(ctx, reqBody, variables, &respData); err != nil { - return nil, err - } - - return respData.XPub, nil -} - -// GetAccessKey will get an access key by id -func (g *TransportGraphQL) GetAccessKey(ctx context.Context, id string) (*buxmodels.AccessKey, ResponseError) { - reqBody := ` - query ($id: String) { - access_key ( - id: $id - ) { - id - xpub_id - key - metadata - created_at - updated_at - deleted_at - revoked_at - } - }` - - var respData AccessKeyData - if err := g.doGraphQLQuery(ctx, reqBody, map[string]interface{}{ - FieldID: id, - }, &respData); err != nil { - return nil, err - } - - return respData.AccessKey, nil -} - -// GetAccessKeys will get all access keys filtered by the metadata -func (g *TransportGraphQL) GetAccessKeys(ctx context.Context, metadata *buxmodels.Metadata) ([]*buxmodels.AccessKey, ResponseError) { - reqBody := ` - query ($metadata: Metadata) { - access_keys ( - metadata: $metadata - ) { - id - xpub_id - key - metadata - created_at - updated_at - deleted_at - revoked_at - } - }` - variables := map[string]interface{}{ - FieldMetadata: processMetadata(metadata), - } - - var respData AccessKeysData - if err := g.doGraphQLQuery(ctx, reqBody, variables, &respData); err != nil { - return nil, err - } - - return respData.AccessKeys, nil -} - -// CreateAccessKey will create new access key -func (g *TransportGraphQL) CreateAccessKey(ctx context.Context, metadata *buxmodels.Metadata) (*buxmodels.AccessKey, ResponseError) { - reqBody := ` - mutation ($metadata: Metadata) { - access_key ( - metadata: $metadata - ) { - id - xpub_id - key - metadata - created_at - updated_at - deleted_at - revoked_at - } - }` - variables := map[string]interface{}{ - FieldMetadata: processMetadata(metadata), - } - - var respData AccessKeyData - if err := g.doGraphQLQuery(ctx, reqBody, variables, &respData); err != nil { - return nil, err - } - - return respData.AccessKey, nil -} - -// GetAccessKeysCount will get the count of access keys -func (g *TransportGraphQL) GetAccessKeysCount(ctx context.Context, conditions map[string]interface{}, metadata *buxmodels.Metadata) (int64, ResponseError) { - reqBody := ` - query ($conditions: Map, $metadata: Metadata) { - access_keys_count ( - conditions: $conditions - metadata: $metadata - ) - }` - variables := map[string]interface{}{ - "conditions": conditions, - "metadata": metadata, - } - var count int64 - if err := g.doGraphQLQuery(ctx, reqBody, variables, &count); err != nil { - return 0, err - } - - return count, nil -} - -// RevokeAccessKey will revoke the given access key -func (g *TransportGraphQL) RevokeAccessKey(ctx context.Context, id string) (*buxmodels.AccessKey, ResponseError) { - reqBody := ` - mutation ($id: String) { - access_key_revoke ( - id: $id - ) { - id - xpub_id - key - metadata - created_at - updated_at - deleted_at - revoked_at - } - }` - variables := map[string]interface{}{ - FieldID: id, - } - - var respData AccessKeyData - if err := g.doGraphQLQuery(ctx, reqBody, variables, &respData); err != nil { - return nil, err - } - - return respData.AccessKey, nil -} - -// GetDestinationByID will get a destination by the given id -func (g *TransportGraphQL) GetDestinationByID(ctx context.Context, id string) (*buxmodels.Destination, ResponseError) { - reqBody := `{ - query ($id: String) { - destination ( - id: $id - ) { - id - xpub_id - locking_script - type - chain - num - address - metadata - created_at - updated_at - deleted_at - } - }` - variables := map[string]interface{}{ - FieldID: id, - } - - var respData DestinationData - if err := g.doGraphQLQuery(ctx, reqBody, variables, &respData); err != nil { - return nil, err - } - - return respData.Destination, nil -} - -// GetDestinationByLockingScript will get a destination by the given locking script -func (g *TransportGraphQL) GetDestinationByLockingScript(ctx context.Context, lockingScript string) (*buxmodels.Destination, ResponseError) { - reqBody := `{ - query ($lockingScript: String) { - destination ( - locking_script: $lockingScript - ) { - id - xpub_id - locking_script - type - chain - num - address - metadata - created_at - updated_at - deleted_at - } - }` - variables := map[string]interface{}{ - FieldLockingScript: lockingScript, - } - - var respData DestinationData - if err := g.doGraphQLQuery(ctx, reqBody, variables, &respData); err != nil { - return nil, err - } - - return respData.Destination, nil -} - -// GetDestinationByAddress will get a destination by the given address -func (g *TransportGraphQL) GetDestinationByAddress(ctx context.Context, address string) (*buxmodels.Destination, ResponseError) { - reqBody := `{ - query ($address: String) { - destination ( - address: $address - ) { - id - xpub_id - locking_script - type - chain - num - address - metadata - created_at - updated_at - deleted_at - } - }` - variables := map[string]interface{}{ - FieldAddress: address, - } - - var respData DestinationData - if err := g.doGraphQLQuery(ctx, reqBody, variables, &respData); err != nil { - return nil, err - } - - return respData.Destination, nil -} - -// UpdateDestinationMetadataByID updates the destination metadata by id -func (g *TransportGraphQL) UpdateDestinationMetadataByID(ctx context.Context, id string, metadata *buxmodels.Metadata) (*buxmodels.Destination, ResponseError) { - reqBody := `{ - mutation ($id: String, $metadata: Metadata!) { - destination_metadata ( - id: $id - metadata: $metadata - ) { - id - xpub_id - locking_script - type - chain - num - address - metadata - created_at - updated_at - deleted_at - } - }` - variables := map[string]interface{}{ - FieldID: id, - FieldMetadata: processMetadata(metadata), - } - - var respData DestinationMetadataData - if err := g.doGraphQLQuery(ctx, reqBody, variables, &respData); err != nil { - return nil, err - } - - return respData.Destination, nil -} - -// UpdateDestinationMetadataByAddress updates the destination metadata by address -func (g *TransportGraphQL) UpdateDestinationMetadataByAddress(ctx context.Context, address string, metadata *buxmodels.Metadata) (*buxmodels.Destination, ResponseError) { - reqBody := `{ - mutation ($address: String, $metadata: Metadata!) { - destination_metadata ( - address: $address - metadata: $metadata - ) { - id - xpub_id - locking_script - type - chain - num - address - metadata - created_at - updated_at - deleted_at - } - }` - variables := map[string]interface{}{ - FieldAddress: address, - FieldMetadata: processMetadata(metadata), - } - - var respData DestinationMetadataData - if err := g.doGraphQLQuery(ctx, reqBody, variables, &respData); err != nil { - return nil, err - } - - return respData.Destination, nil -} - -// UpdateDestinationMetadataByLockingScript updates the destination metadata by lockingScript -func (g *TransportGraphQL) UpdateDestinationMetadataByLockingScript(ctx context.Context, lockingScript string, metadata *buxmodels.Metadata) (*buxmodels.Destination, ResponseError) { - reqBody := `{ - mutation ($locking_script: String, $metadata: Metadata!) { - destination_metadata ( - locking_script: $locking_script - metadata: $metadata - ) { - id - xpub_id - locking_script - type - chain - num - address - metadata - created_at - updated_at - deleted_at - } - }` - variables := map[string]interface{}{ - FieldLockingScript: lockingScript, - FieldMetadata: processMetadata(metadata), - } - - var respData DestinationMetadataData - if err := g.doGraphQLQuery(ctx, reqBody, variables, &respData); err != nil { - return nil, err - } - - return respData.Destination, nil -} - -// GetDestinations will get all destinations filtered by the medata conditions -func (g *TransportGraphQL) GetDestinations(ctx context.Context, metadataConditions *buxmodels.Metadata) ([]*buxmodels.Destination, ResponseError) { - reqBody := `{ - query ($metadata: Metadata) { - destinations ( - metadata: $metadata - ) { - id - xpub_id - locking_script - type - chain - num - address - metadata - created_at - updated_at - deleted_at - } - }` - variables := map[string]interface{}{ - FieldMetadata: processMetadata(metadataConditions), - } - - var respData DestinationsData - if err := g.doGraphQLQuery(ctx, reqBody, variables, &respData); err != nil { - return nil, err - } - - return respData.Destinations, nil -} - -// GetDestinationsCount will get the count of destinations matching the metadata filter -func (g *TransportGraphQL) GetDestinationsCount(ctx context.Context, conditions map[string]interface{}, metadata *buxmodels.Metadata) (int64, ResponseError) { - reqBody := ` - query ($conditions: Map, $metadata: Metadata) { - destinations_count ( - conditions: $conditions - metadata: $metadata - ) - }` - variables := map[string]interface{}{ - "conditions": conditions, - "metadata": metadata, - } - var count int64 - if err := g.doGraphQLQuery(ctx, reqBody, variables, &count); err != nil { - return 0, err - } - - return count, nil -} - -// NewDestination will get a new destination -func (g *TransportGraphQL) NewDestination(ctx context.Context, metadata *buxmodels.Metadata) (*buxmodels.Destination, ResponseError) { - reqBody := ` - mutation ($metadata: Metadata) { - destination( - metadata: $metadata - ) { - id - xpub_id - locking_script - type - chain - num - address - metadata - } - }` - variables := map[string]interface{}{ - FieldMetadata: processMetadata(metadata), - } - - var respData DestinationData - if err := g.doGraphQLQuery(ctx, reqBody, variables, &respData); err != nil { - return nil, err - } - - return respData.Destination, nil -} - -// GetTransaction get a transaction by ID -func (g *TransportGraphQL) GetTransaction(ctx context.Context, txID string) (*buxmodels.Transaction, ResponseError) { - reqBody := ` - query { - transaction( - id:"` + txID + `", - ) { - id - hex - block_hash - block_height - fee - number_of_inputs - number_of_outputs - output_value - total_value - direction - metadata - created_at - updated_at - deleted_at - } - }` - var respData TransactionData - if err := g.doGraphQLQuery(ctx, reqBody, nil, &respData); err != nil { - return nil, err - } - - return respData.Transaction, nil -} - -// GetTransactions get a transactions, filtered by the given metadata -func (g *TransportGraphQL) GetTransactions(ctx context.Context, conditions map[string]interface{}, - metadataConditions *buxmodels.Metadata, queryParams *QueryParams, //nolint:revive // TODO: implement this field -) ([]*buxmodels.Transaction, ResponseError) { - querySignature := "" - queryArguments := "" - - // is there a better way to do this ? - if conditions != nil { - querySignature += "( $conditions Map " - queryArguments += " conditions: $conditions\n" - } - if metadataConditions != nil { - if conditions == nil { - querySignature += "( " - } else { - querySignature += ", " - } - querySignature += "$metadata Map" - queryArguments += " metadata: $metadata\n" - } else { - querySignature += " )" - } - - reqBody := ` - query ` + querySignature + `{ - transactions ` + queryArguments + ` { - id - hex - block_hash - block_height - fee - number_of_inputs - number_of_outputs - output_value - total_value - direction - metadata - created_at - updated_at - deleted_at - } - }` - variables := make(map[string]interface{}) - if conditions != nil { - variables[FieldConditions] = conditions - } - if metadataConditions != nil { - variables[FieldMetadata] = metadataConditions - } - - var respData TransactionsData - if err := g.doGraphQLQuery(ctx, reqBody, variables, &respData); err != nil { - return nil, err - } - - return respData.Transactions, nil -} - -// GetTransactionsCount get number of user transactions -func (g *TransportGraphQL) GetTransactionsCount(ctx context.Context, conditions map[string]interface{}, metadata *buxmodels.Metadata) (int64, ResponseError) { - reqBody := ` - query ($conditions: Map, $metadata: Metadata) { - transactions_count ( - conditions: $conditions - metadata: $metadata - ) - }` - variables := map[string]interface{}{ - "conditions": conditions, - "metadata": metadata, - } - var respData int64 - if err := g.doGraphQLQuery(ctx, reqBody, variables, &respData); err != nil { - return 0, err - } - - return respData, nil -} - -// DraftToRecipients is a draft transaction to a slice of recipients -func (g *TransportGraphQL) DraftToRecipients(ctx context.Context, recipients []*Recipients, - metadata *buxmodels.Metadata, -) (*buxmodels.DraftTransaction, ResponseError) { - reqBody := ` - mutation ($outputs: [TransactionOutputInput]!, $metadata: Metadata) { - new_transaction( - transaction_config:{ - outputs: $outputs - change_number_of_destinations:3 - change_destinations_strategy:"random" - } - metadata:$metadata - ) ` + graphqlDraftTransactionFields + ` - }` - req := graphql.NewRequest(reqBody) - outputs := make([]map[string]interface{}, 0) - for _, recipient := range recipients { - outputs = append(outputs, map[string]interface{}{ - FieldTo: recipient.To, - FieldSatoshis: recipient.Satoshis, - FieldOpReturn: recipient.OpReturn, - }) - } - req.Var(FieldOutputs, outputs) - req.Var(FieldMetadata, processMetadata(metadata)) - variables := map[string]interface{}{ - FieldOutputs: outputs, - FieldMetadata: processMetadata(metadata), - } - - return g.draftTransactionCommon(ctx, reqBody, variables, req) -} - -// DraftTransaction is a draft transaction -func (g *TransportGraphQL) DraftTransaction(ctx context.Context, transactionConfig *buxmodels.TransactionConfig, - metadata *buxmodels.Metadata, -) (*buxmodels.DraftTransaction, ResponseError) { - reqBody := ` - mutation ($transactionConfig: TransactionConfigInput!, $metadata: Metadata) { - new_transaction( - transaction_config: $transactionConfig - metadata: $metadata - ) ` + graphqlDraftTransactionFields + ` - }` - req := graphql.NewRequest(reqBody) - req.Var("transactionConfig", transactionConfig) - req.Var(FieldMetadata, processMetadata(metadata)) - variables := map[string]interface{}{ - FieldTransactionConfig: transactionConfig, - FieldMetadata: processMetadata(metadata), - } - - return g.draftTransactionCommon(ctx, reqBody, variables, req) -} - -func (g *TransportGraphQL) draftTransactionCommon(ctx context.Context, reqBody string, - variables map[string]interface{}, req *graphql.Request, -) (*buxmodels.DraftTransaction, ResponseError) { - err := g.signGraphQLRequest(req, reqBody, variables, g.xPriv, g.xPub) - if err != nil { - return nil, err - } - - // run it and capture the response - var respData DraftTransactionData - if err := g.client.Run(ctx, req, &respData); err != nil { - return nil, WrapError(err) - } - draftTransaction := respData.NewTransaction - - return draftTransaction, nil -} - -// RecordTransaction will record a transaction -func (g *TransportGraphQL) RecordTransaction(ctx context.Context, hex, referenceID string, - metadata *buxmodels.Metadata, -) (*buxmodels.Transaction, ResponseError) { - reqBody := ` - mutation($metadata: Metadata) { - transaction( - hex:"` + hex + `", - draft_id:"` + referenceID + `" - metadata: $metadata - ) { - id - hex - block_hash - block_height - fee - number_of_inputs - number_of_outputs - output_value - total_value - direction - metadata - created_at - updated_at - deleted_at - } - }` - req := graphql.NewRequest(reqBody) - req.Var(FieldMetadata, processMetadata(metadata)) - - variables := map[string]interface{}{ - FieldMetadata: processMetadata(metadata), - } - err := g.signGraphQLRequest(req, reqBody, variables, g.xPriv, g.xPub) - if err != nil { - return nil, err - } - - // run it and capture the response - var respData NewTransactionData - if err := g.client.Run(ctx, req, &respData); err != nil { - return nil, WrapError(err) - } - transaction := respData.Transaction - - return transaction, nil -} - -// UpdateTransactionMetadata update the metadata of a transaction -func (g *TransportGraphQL) UpdateTransactionMetadata(ctx context.Context, txID string, metadata *buxmodels.Metadata) (*buxmodels.Transaction, ResponseError) { - reqBody := ` - mutation ($id: String!, $metadata: Metadata!) { - destination_metadata ( - id: $id - metadata: $metadata - ) { - id - hex - block_hash - block_height - fee - number_of_inputs - number_of_outputs - output_value - total_value - direction - metadata - created_at - updated_at - deleted_at - } - }` - variables := map[string]interface{}{ - FieldID: txID, - FieldMetadata: processMetadata(metadata), - } - - var respData TransactionMetadataData - if err := g.doGraphQLQuery(ctx, reqBody, variables, &respData); err != nil { - return nil, err - } - - return respData.Transaction, nil -} - -// GetUtxo will get a utxo by transaction ID -func (g *TransportGraphQL) GetUtxo(ctx context.Context, txID string, outputIndex uint32) (*buxmodels.Utxo, ResponseError) { - reqBody := ` - query ($tx_id: String!, $output_index: Uint32!) { - utxo ( - tx_id: $tx_id - output_index: $output_index - ) { - id - transaction_id - xpub_id - output_index - satoshis - script_pub_key - type - draft_id - reserved_at - spending_tx_id - metadata - transaction - created_at - updated_at - deleted_at - } - }` - - variables := map[string]interface{}{ - FieldTransactionID: txID, - FieldOutputIndex: outputIndex, - } - - var respData UtxoData - if err := g.doGraphQLQuery(ctx, reqBody, variables, &respData); err != nil { - return nil, err - } - - return respData.Utxo, nil -} - -// GetUtxos will get a list of utxos filtered by conditions and metadata -func (g *TransportGraphQL) GetUtxos( - ctx context.Context, - conditions map[string]interface{}, - metadata *buxmodels.Metadata, - queryParams *QueryParams, //nolint:revive // TODO: implement this field -) ([]*buxmodels.Utxo, ResponseError) { - reqBody := ` - query ($conditions: Map, $metadata: Metadata) { - utxos ( - conditions: $conditions - metadata: $metadata - ) - }` - - variables := map[string]interface{}{ - "conditions": conditions, - "metadata": metadata, - } - - var respData UtxosData - if err := g.doGraphQLQuery(ctx, reqBody, variables, &respData); err != nil { - return nil, err - } - - return respData.Utxos, nil -} - -// GetUtxosCount will get the count of utxos filtered by conditions and metadata -func (g *TransportGraphQL) GetUtxosCount( - ctx context.Context, - conditions map[string]interface{}, - metadata *buxmodels.Metadata, -) (int64, ResponseError) { - reqBody := ` - query ($conditions: Map, $metadata: Metadata) { - utxos_count ( - conditions: $conditions - metadata: $metadata - ) - }` - - variables := map[string]interface{}{ - "conditions": conditions, - "metadata": metadata, - } - - var respData int64 - if err := g.doGraphQLQuery(ctx, reqBody, variables, &respData); err != nil { - return 0, err - } - - return respData, nil -} - -// UnreserveUtxos will unreserve utxos from draft transaction -func (g *TransportGraphQL) UnreserveUtxos(ctx context.Context, referenceID string) ResponseError { - reqBody := ` - mutation ($draft_id: String!) { - utxos_unreserve (draft_id: $draft_id) - }` - variables := map[string]interface{}{ - "draft_id": referenceID, - } - - var respData bool - return g.doGraphQLQuery(ctx, reqBody, variables, &respData) -} - -func (g *TransportGraphQL) doGraphQLQuery(ctx context.Context, reqBody string, variables map[string]interface{}, - respData interface{}, -) ResponseError { - req := graphql.NewRequest(reqBody) - for key, value := range variables { - req.Var(key, value) - } - - err := g.signGraphQLRequest(req, reqBody, variables, g.xPriv, g.xPub) - if err != nil { - return err - } - - // run it and capture the response - if err := g.client.Run(ctx, req, &respData); err != nil { - return WrapError(err) - } - - return nil -} - -func getBodyString(reqBody string, variables map[string]interface{}) (string, ResponseError) { - requestBodyObj := struct { - Query string `json:"query"` - Variables map[string]interface{} `json:"variables"` - }{ - Query: reqBody, - Variables: variables, - } - - body, err := json.Marshal(requestBodyObj) - if err != nil { - return "", WrapError(err) - } - - return string(body), nil -} - -func (g *TransportGraphQL) signGraphQLRequest(req *graphql.Request, reqBody string, variables map[string]interface{}, - xPriv *bip32.ExtendedKey, xPub *bip32.ExtendedKey, -) ResponseError { - if xPriv != nil || xPub != nil { - return g.authenticateWithXpriv(req, reqBody, variables, xPriv, xPub) - } else if g.accessKey != nil { - return g.authenticateWithAccessKey(req, reqBody, variables) - } else { - return WrapError(buxerrors.ErrMissingXPriv) - } -} - -func (g *TransportGraphQL) authenticateWithXpriv(req *graphql.Request, reqBody string, variables map[string]interface{}, xPriv *bip32.ExtendedKey, xPub *bip32.ExtendedKey) ResponseError { - if g.signRequest { - bodyString, err := getBodyString(reqBody, variables) - if err != nil { - return err - } - err = addSignature(&req.Header, xPriv, bodyString) - if err != nil { - return err - } - } else { - req.Header.Set(buxmodels.AuthHeader, xPub.String()) - } - return nil -} - -func (g *TransportGraphQL) authenticateWithAccessKey(req *graphql.Request, reqBody string, variables map[string]interface{}) ResponseError { - bodyString, err := getBodyString(reqBody, variables) - if err != nil { - return err - } - return SetSignatureFromAccessKey(&req.Header, hex.EncodeToString(g.accessKey.Serialise()), bodyString) -} - -const graphqlDraftTransactionFields = `{ -id -xpub_id -configuration { - inputs { - id - satoshis - transaction_id - output_index - script_pub_key - destination { - id - address - type - num - chain - locking_script - } - } - outputs { - to - satoshis - scripts { - address - satoshis - script - } - paymail_p4 { - alias - domain - from_paymail - note - pub_key - receive_endpoint - reference_id - resolution_type - } - } - change_destinations { - address - chain - num - locking_script - draft_id - } - change_satoshis - fee -} -status -expires_at -hex -}` diff --git a/transports/graphql_admin.go b/transports/graphql_admin.go deleted file mode 100644 index 1cc65187..00000000 --- a/transports/graphql_admin.go +++ /dev/null @@ -1,551 +0,0 @@ -package transports - -import ( - "context" - buxmodels "github.com/BuxOrg/bux-models" - "github.com/machinebox/graphql" -) - -// NewXpub will register an xPub -func (g *TransportGraphQL) NewXpub(ctx context.Context, rawXPub string, metadata *buxmodels.Metadata) ResponseError { - // adding a xpub needs to be signed by an admin key - if g.adminXPriv == nil { - return WrapError(ErrAdminKey) - } - - reqBody := ` - mutation ($metadata: Metadata) { - xpub( - xpub: "` + rawXPub + `" - metadata: $metadata - ) { - id - } - }` - req := graphql.NewRequest(reqBody) - req.Var(FieldMetadata, processMetadata(metadata)) - variables := map[string]interface{}{ - FieldMetadata: processMetadata(metadata), - } - - bodyString, err := getBodyString(reqBody, variables) - if err != nil { - return err - } - if err := addSignature(&req.Header, g.adminXPriv, bodyString); err != nil { - return err - } - - // run it and capture the response - var xPubData interface{} - - return WrapError(g.client.Run(ctx, req, &xPubData)) -} - -// RegisterXpub alias for NewXpub -func (g *TransportGraphQL) RegisterXpub(ctx context.Context, rawXPub string, metadata *buxmodels.Metadata) ResponseError { - return g.NewXpub(ctx, rawXPub, metadata) -} - -// AdminGetStatus get whether admin key is valid -func (g *TransportGraphQL) AdminGetStatus(ctx context.Context) (bool, ResponseError) { - reqBody := ` - query { - admin_get_status - }` - - var status bool - if err := g.doGraphQLAdminQuery(ctx, reqBody, nil, &status); err != nil { - return false, err - } - - return status, nil -} - -// AdminGetStats get admin stats -func (g *TransportGraphQL) AdminGetStats(ctx context.Context) (*buxmodels.AdminStats, ResponseError) { - reqBody := ` - query { - admin_get_stats { - balance - destinations - transactions - paymails - utxos - xpubs - transactions_per_day - utxos_per_type - } - }` - - var stats *buxmodels.AdminStats - if err := g.doGraphQLAdminQuery(ctx, reqBody, nil, &stats); err != nil { - return nil, err - } - - return stats, nil -} - -// AdminGetAccessKeys get all access keys filtered by conditions -func (g *TransportGraphQL) AdminGetAccessKeys(ctx context.Context, conditions map[string]interface{}, - metadata *buxmodels.Metadata, queryParams *QueryParams, -) ([]*buxmodels.AccessKey, ResponseError) { - var models []*buxmodels.AccessKey - method := `admin_access_keys_list` - fields := ` - id - xpub_id - key - metadata - created_at - updated_at - deleted_at - revoked_at - ` - - if err := g.adminGetModels(ctx, conditions, metadata, queryParams, method, fields, &models); err != nil { - return nil, err - } - - return models, nil -} - -// AdminGetAccessKeysCount get a count of all the access keys filtered by conditions -func (g *TransportGraphQL) AdminGetAccessKeysCount(ctx context.Context, conditions map[string]interface{}, - metadata *buxmodels.Metadata, -) (int64, ResponseError) { - return g.adminCount(ctx, conditions, metadata, "admin_access_keys_count") -} - -// AdminGetBlockHeaders get all block headers filtered by conditions -func (g *TransportGraphQL) AdminGetBlockHeaders(ctx context.Context, conditions map[string]interface{}, - metadata *buxmodels.Metadata, queryParams *QueryParams, -) ([]*buxmodels.BlockHeader, ResponseError) { - var models []*buxmodels.BlockHeader - method := `admin_block_headers_list` - fields := ` - id - height - time - nonce - version - hash_previous_block - hash_merkle_root - bits - synced - created_at - updated_at - deleted_at - ` - - if err := g.adminGetModels(ctx, conditions, metadata, queryParams, method, fields, &models); err != nil { - return nil, err - } - - return models, nil -} - -// AdminGetBlockHeadersCount get a count of all the block headers filtered by conditions -func (g *TransportGraphQL) AdminGetBlockHeadersCount(ctx context.Context, conditions map[string]interface{}, - metadata *buxmodels.Metadata, -) (int64, ResponseError) { - return g.adminCount(ctx, conditions, metadata, "admin_block_headers_count") -} - -// AdminGetDestinations get all block destinations filtered by conditions -func (g *TransportGraphQL) AdminGetDestinations(ctx context.Context, conditions map[string]interface{}, - metadata *buxmodels.Metadata, queryParams *QueryParams, -) ([]*buxmodels.Destination, ResponseError) { - var models []*buxmodels.Destination - method := `admin_destinations_list` - fields := ` - id - xpub_id - locking_script - type - chain - num - address - draft_id - metadata - created_at - updated_at - deleted_at - ` - - if err := g.adminGetModels(ctx, conditions, metadata, queryParams, method, fields, &models); err != nil { - return nil, err - } - - return models, nil -} - -// AdminGetDestinationsCount get a count of all the destinations filtered by conditions -func (g *TransportGraphQL) AdminGetDestinationsCount(ctx context.Context, conditions map[string]interface{}, - metadata *buxmodels.Metadata, -) (int64, ResponseError) { - return g.adminCount(ctx, conditions, metadata, "admin_destinations_count") -} - -// AdminGetPaymail get a paymail by address -func (g *TransportGraphQL) AdminGetPaymail(ctx context.Context, address string) (*buxmodels.PaymailAddress, ResponseError) { - reqBody := ` - query ($address: String!) { - admin_paymail_get ( - address: $address - ) { - id - xpub_id - alias - domain - public_name - avatar - created_at - updated_at - deleted_at - } - }` - - variables := map[string]interface{}{ - FieldAddress: address, - } - - var paymail *buxmodels.PaymailAddress - if err := g.doGraphQLAdminQuery(ctx, reqBody, variables, &paymail); err != nil { - return nil, err - } - - return paymail, nil -} - -// AdminGetPaymails get all block paymails filtered by conditions -func (g *TransportGraphQL) AdminGetPaymails(ctx context.Context, conditions map[string]interface{}, - metadata *buxmodels.Metadata, queryParams *QueryParams, -) ([]*buxmodels.PaymailAddress, ResponseError) { - var models []*buxmodels.PaymailAddress - method := `admin_paymails_list` - fields := ` - id - xpub_id - alias - domain - public_name - avatar - created_at - updated_at - deleted_at - ` - - if err := g.adminGetModels(ctx, conditions, metadata, queryParams, method, fields, &models); err != nil { - return nil, err - } - - return models, nil -} - -// AdminGetPaymailsCount get a count of all the paymails filtered by conditions -func (g *TransportGraphQL) AdminGetPaymailsCount(ctx context.Context, conditions map[string]interface{}, - metadata *buxmodels.Metadata, -) (int64, ResponseError) { - return g.adminCount(ctx, conditions, metadata, "admin_paymails_count") -} - -// AdminCreatePaymail create a new paymail for a xpub -func (g *TransportGraphQL) AdminCreatePaymail(ctx context.Context, xPubID string, address string, publicName string, - avatar string, -) (*buxmodels.PaymailAddress, ResponseError) { - reqBody := ` - mutation ( - $xpub_id: String! - $address: String! - $public_name: String! - $avatar: String! - ) { - admin_paymail_create ( - xpub_id: $xpub_id - address: $address - public_name: $public_name - avatar: $avatar - ) { - id - xpub_id - alias - domain - public_name - avatar - created_at - updated_at - deleted_at - } - }` - - variables := map[string]interface{}{ - FieldXpubID: xPubID, - FieldAddress: address, - FieldPublicName: publicName, - FieldAvatar: avatar, - } - - var paymail *buxmodels.PaymailAddress - if err := g.doGraphQLAdminQuery(ctx, reqBody, variables, &paymail); err != nil { - return nil, err - } - - return paymail, nil -} - -// AdminDeletePaymail delete a paymail address from the database -func (g *TransportGraphQL) AdminDeletePaymail(ctx context.Context, address string) (*buxmodels.PaymailAddress, ResponseError) { - reqBody := ` - mutation ( - $address: String! - ) { - admin_paymail_delete ( - address: $address - ) { - id - xpub_id - alias - domain - public_name - avatar - created_at - updated_at - deleted_at - } - }` - - variables := map[string]interface{}{ - FieldAddress: address, - } - - var paymail *buxmodels.PaymailAddress - if err := g.doGraphQLAdminQuery(ctx, reqBody, variables, &paymail); err != nil { - return nil, err - } - - return paymail, nil -} - -// AdminGetTransactions get all block transactions filtered by conditions -func (g *TransportGraphQL) AdminGetTransactions(ctx context.Context, conditions map[string]interface{}, - metadata *buxmodels.Metadata, queryParams *QueryParams, -) ([]*buxmodels.Transaction, ResponseError) { - var models []*buxmodels.Transaction - method := `admin_transactions_list` - fields := ` - id - hex - block_hash - block_height - fee - number_of_inputs - number_of_outputs - output_value - total_value - metadata - created_at - updated_at - deleted_at - ` - - if err := g.adminGetModels(ctx, conditions, metadata, queryParams, method, fields, &models); err != nil { - return nil, err - } - - return models, nil -} - -// AdminGetTransactionsCount get a count of all the transactions filtered by conditions -func (g *TransportGraphQL) AdminGetTransactionsCount(ctx context.Context, conditions map[string]interface{}, - metadata *buxmodels.Metadata, -) (int64, ResponseError) { - return g.adminCount(ctx, conditions, metadata, "admin_transactions_count") -} - -// AdminGetUtxos get all block utxos filtered by conditions -func (g *TransportGraphQL) AdminGetUtxos(ctx context.Context, conditions map[string]interface{}, - metadata *buxmodels.Metadata, queryParams *QueryParams, -) ([]*buxmodels.Utxo, ResponseError) { - var models []*buxmodels.Utxo - method := `admin_utxos_list` - fields := ` - id - xpub_id - satoshis - script_pub_key - type - draft_id - reserved_at - spending_tx_id - created_at - updated_at - deleted_at - ` - - if err := g.adminGetModels(ctx, conditions, metadata, queryParams, method, fields, &models); err != nil { - return nil, err - } - - return models, nil -} - -// AdminGetUtxosCount get a count of all the utxos filtered by conditions -func (g *TransportGraphQL) AdminGetUtxosCount(ctx context.Context, conditions map[string]interface{}, metadata *buxmodels.Metadata) (int64, ResponseError) { - return g.adminCount(ctx, conditions, metadata, "admin_utxos_count") -} - -// AdminGetXPubs get all block xpubs filtered by conditions -func (g *TransportGraphQL) AdminGetXPubs(ctx context.Context, conditions map[string]interface{}, - metadata *buxmodels.Metadata, queryParams *QueryParams, -) ([]*buxmodels.Xpub, ResponseError) { - var models []*buxmodels.Xpub - method := `admin_xpubs_list` - fields := ` - id - current_balance - next_internal_num - next_external_num - metadata - created_at - updated_at - deleted_at - ` - - if err := g.adminGetModels(ctx, conditions, metadata, queryParams, method, fields, &models); err != nil { - return nil, err - } - - return models, nil -} - -// AdminGetXPubsCount get a count of all the xpubs filtered by conditions -func (g *TransportGraphQL) AdminGetXPubsCount(ctx context.Context, conditions map[string]interface{}, metadata *buxmodels.Metadata) (int64, ResponseError) { - return g.adminCount(ctx, conditions, metadata, "admin_xpubs_count") -} - -func (g *TransportGraphQL) adminGetModels(ctx context.Context, conditions map[string]interface{}, - metadata *buxmodels.Metadata, queryParams *QueryParams, method string, fields string, - models interface{}, -) ResponseError { - reqBody := ` - query ($conditions: Map, $metadata: Metadata, $params: QueryParams) { - ` + method + ` ( - conditions: $conditions - metadata: $metadata - params: $params - ) { - ` + fields + ` - } - }` - - variables := map[string]interface{}{ - FieldConditions: conditions, - FieldMetadata: processMetadata(metadata), - FieldQueryParams: queryParams, - } - - return g.doGraphQLAdminQuery(ctx, reqBody, variables, &models) -} - -func (g *TransportGraphQL) adminCount(ctx context.Context, conditions map[string]interface{}, metadata *buxmodels.Metadata, - method string, -) (int64, ResponseError) { - // adding a xpub needs to be signed by an admin key - if g.adminXPriv == nil { - return 0, WrapError(ErrAdminKey) - } - - reqBody := ` - query ($conditions: Map, $metadata: Metadata) { - ` + method + ` ( - conditions: $conditions - metadata: $metadata - ) - }` - - req := graphql.NewRequest(reqBody) - req.Var(FieldConditions, conditions) - req.Var(FieldMetadata, processMetadata(metadata)) - variables := map[string]interface{}{ - FieldConditions: conditions, - FieldMetadata: processMetadata(metadata), - } - - bodyString, err := getBodyString(reqBody, variables) - if err != nil { - return 0, err - } - if err = addSignature(&req.Header, g.adminXPriv, bodyString); err != nil { - return 0, err - } - - // run it and capture the response - var count int64 - if err := g.client.Run(ctx, req, &count); err != nil { - return 0, WrapError(err) - } - - return count, nil -} - -func (g *TransportGraphQL) doGraphQLAdminQuery(ctx context.Context, reqBody string, variables map[string]interface{}, - respData interface{}, -) ResponseError { - req := graphql.NewRequest(reqBody) - for key, value := range variables { - req.Var(key, value) - } - - err := g.signGraphQLRequest(req, reqBody, variables, g.adminXPriv, nil) - if err != nil { - return err - } - - // run it and capture the response - if err := g.client.Run(ctx, req, &respData); err != nil { - return WrapError(err) - } - - return nil -} - -// AdminRecordTransaction will record a transaction as an admin -func (g *TransportGraphQL) AdminRecordTransaction(ctx context.Context, hex string) (*buxmodels.Transaction, ResponseError) { - reqBody := ` - mutation() { - admin_transaction ( - hex:"` + hex + `", - ) { - id - hex - block_hash - block_height - fee - number_of_inputs - number_of_outputs - output_value - total_value - direction - metadata - created_at - updated_at - deleted_at - } - }` - req := graphql.NewRequest(reqBody) - - err := g.signGraphQLRequest(req, reqBody, nil, g.xPriv, g.xPub) - if err != nil { - return nil, err - } - - // run it and capture the response - var respData NewTransactionData - if err := g.client.Run(ctx, req, &respData); err != nil { - return nil, WrapError(err) - } - transaction := respData.Transaction - - return transaction, nil -} diff --git a/transports/graphql_test.go b/transports/graphql_test.go deleted file mode 100644 index c6896548..00000000 --- a/transports/graphql_test.go +++ /dev/null @@ -1,252 +0,0 @@ -package transports - -import ( - "context" - "encoding/json" - "errors" - "testing" - - buxmodels "github.com/BuxOrg/bux-models" - buxerrors "github.com/BuxOrg/bux-models/bux-errors" - "github.com/BuxOrg/go-buxclient/utils" - "github.com/libsv/go-bk/bip32" - "github.com/machinebox/graphql" - "github.com/stretchr/testify/assert" -) - -const ( - xPrivString = "xprv9s21ZrQH143K3N6qVJQAu4EP51qMcyrKYJLkLgmYXgz58xmVxVLSsbx2DfJUtjcnXK8NdvkHMKfmmg5AJT2nqqRWUrjSHX29qEJwBgBPkJQ" - xPubString = "xpub661MyMwAqRbcFrBJbKwBGCB7d3fr2SaAuXGM95BA62X41m6eW2ehRQGW4xLi9wkEXUGnQZYxVVj4PxXnyrLk7jdqvBAs1Qq9gf6ykMvjR7J" -) - -type TransportGraphQLMock struct { - TransportGraphQL - client *GraphQLMockClient -} - -func (t *TransportGraphQLMock) Init() error { - t.client = &GraphQLMockClient{} - return nil -} - -type GraphQLMockClient struct { - Response interface{} - Request *graphql.Request - Error error -} - -func (g *GraphQLMockClient) Run(_ context.Context, req *graphql.Request, resp interface{}) error { - j, _ := json.Marshal(g.Response) //nolint:errchkjson // used for testing only - _ = json.Unmarshal(j, &resp) - g.Request = req - return g.Error -} - -// TestNewXpub will test the NewXpub method -func TestNewXpub(t *testing.T) { - xPriv, _ := bip32.NewKeyFromString(xPrivString) - // xPub, _ := xPriv.Neuter() - - t.Run("no admin key", func(t *testing.T) { - client := TransportGraphQLMock{ - TransportGraphQL: TransportGraphQL{}, - } - err := client.NewXpub(context.Background(), xPubString, nil) - assert.Equal(t, err.Error(), ErrAdminKey.Error()) - }) - - t.Run("return error", func(t *testing.T) { - errTestTerror := errors.New("test error") - client := TransportGraphQLMock{ - TransportGraphQL: TransportGraphQL{ - adminXPriv: xPriv, - client: &GraphQLMockClient{ - Error: errTestTerror, - }, - }, - } - err := client.NewXpub(context.Background(), xPubString, nil) - assert.Equal(t, err.Error(), errTestTerror.Error()) - }) - - t.Run("return success", func(t *testing.T) { - graphqlClient := GraphQLMockClient{ - Response: buxmodels.Xpub{ - ID: utils.Hash(xPubString), - CurrentBalance: 0, - NextInternalNum: 0, - NextExternalNum: 0, - }, - } - client := TransportGraphQLMock{ - TransportGraphQL: TransportGraphQL{ - adminXPriv: xPriv, - client: &graphqlClient, - }, - } - err := client.NewXpub(context.Background(), xPubString, nil) - assert.NoError(t, err) - }) -} - -// TestGetDestination will test the GetDestination method -func TestGetDestination(t *testing.T) { - xPriv, _ := bip32.NewKeyFromString(xPrivString) - xPub, _ := xPriv.Neuter() - - t.Run("missing xpriv", func(t *testing.T) { - client := TransportGraphQLMock{ - TransportGraphQL: TransportGraphQL{ - signRequest: true, - client: &GraphQLMockClient{}, - }, - } - destination, err := client.NewDestination(context.Background(), nil) - assert.Equal(t, err.Error(), buxerrors.ErrMissingXPriv.Error()) - assert.Nil(t, destination) - }) - - t.Run("signRequest success", func(t *testing.T) { - graphqlClient := GraphQLMockClient{ - Response: DestinationData{ - Destination: &buxmodels.Destination{ - Address: "test-address", - }, - }, - } - client := TransportGraphQLMock{ - TransportGraphQL: TransportGraphQL{ - xPriv: xPriv, - xPub: xPub, - signRequest: true, - client: &graphqlClient, - }, - } - destination, err := client.NewDestination(context.Background(), nil) - assert.NoError(t, err) - assert.IsType(t, &buxmodels.Destination{}, destination) - assert.Equal(t, "test-address", destination.Address) - checkAuthHeaders(t, graphqlClient) - }) - - t.Run("no signRequest success", func(t *testing.T) { - graphqlClient := GraphQLMockClient{ - Response: DestinationData{ - Destination: &buxmodels.Destination{ - Address: "test-address", - }, - }, - } - client := TransportGraphQLMock{ - TransportGraphQL: TransportGraphQL{ - xPriv: xPriv, - xPub: xPub, - client: &graphqlClient, - }, - } - destination, err := client.NewDestination(context.Background(), nil) - assert.NoError(t, err) - assert.IsType(t, &buxmodels.Destination{}, destination) - assert.Equal(t, "test-address", destination.Address) - assert.Len(t, graphqlClient.Request.Header, 1) - assert.Contains(t, graphqlClient.Request.Header, "Bux-Auth-Xpub") - }) -} - -// TestDraftTransaction will test the DraftTransaction method -func TestDraftTransaction(t *testing.T) { - xPriv, _ := bip32.NewKeyFromString(xPrivString) - xPub, _ := xPriv.Neuter() - config := &buxmodels.TransactionConfig{ - SendAllTo: &buxmodels.TransactionOutput{ - To: "bux@bux.org", - }, - } - - t.Run("missing xpriv", func(t *testing.T) { - client := TransportGraphQLMock{ - TransportGraphQL: TransportGraphQL{ - signRequest: true, - client: &GraphQLMockClient{}, - }, - } - destination, err := client.DraftTransaction(context.Background(), config, nil) - assert.Equal(t, err.Error(), buxerrors.ErrMissingXPriv.Error()) - assert.Nil(t, destination) - }) - - t.Run("signRequest success", func(t *testing.T) { - graphqlClient := GraphQLMockClient{ - Response: DraftTransactionData{ - NewTransaction: &buxmodels.DraftTransaction{ - Status: buxmodels.DraftStatusDraft, - }, - }, - } - client := TransportGraphQLMock{ - TransportGraphQL: TransportGraphQL{ - xPriv: xPriv, - xPub: xPub, - client: &graphqlClient, - signRequest: true, - }, - } - draftTransaction, err := client.DraftTransaction(context.Background(), config, nil) - assert.NoError(t, err) - assert.IsType(t, &buxmodels.DraftTransaction{}, draftTransaction) - checkAuthHeaders(t, graphqlClient) - }) -} - -// TestDraftToRecipients will test the DraftToRecipients method -func TestDraftToRecipients(t *testing.T) { - xPriv, _ := bip32.NewKeyFromString(xPrivString) - xPub, _ := xPriv.Neuter() - recipients := []*Recipients{{ - To: "bux@bux.org", - Satoshis: 12125, - }} - - t.Run("missing xpriv", func(t *testing.T) { - client := TransportGraphQLMock{ - TransportGraphQL: TransportGraphQL{ - signRequest: true, - client: &GraphQLMockClient{}, - }, - } - destination, err := client.DraftToRecipients(context.Background(), recipients, nil) - assert.Equal(t, err.Error(), buxerrors.ErrMissingXPriv.Error()) - assert.Nil(t, destination) - }) - - t.Run("signRequest success", func(t *testing.T) { - graphqlClient := GraphQLMockClient{ - Response: DraftTransactionData{ - NewTransaction: &buxmodels.DraftTransaction{ - Status: buxmodels.DraftStatusDraft, - }, - }, - } - client := TransportGraphQLMock{ - TransportGraphQL: TransportGraphQL{ - xPriv: xPriv, - xPub: xPub, - client: &graphqlClient, - signRequest: true, - }, - } - draftTransaction, err := client.DraftToRecipients(context.Background(), recipients, nil) - assert.NoError(t, err) - assert.IsType(t, &buxmodels.DraftTransaction{}, draftTransaction) - checkAuthHeaders(t, graphqlClient) - }) -} - -func checkAuthHeaders(t *testing.T, graphqlClient GraphQLMockClient) { - assert.Len(t, graphqlClient.Request.Header, 5) - assert.Contains(t, graphqlClient.Request.Header, "Bux-Auth-Hash") - assert.Contains(t, graphqlClient.Request.Header, "Bux-Auth-Nonce") - assert.Contains(t, graphqlClient.Request.Header, "Bux-Auth-Signature") - assert.Contains(t, graphqlClient.Request.Header, "Bux-Auth-Time") - assert.Contains(t, graphqlClient.Request.Header, "Bux-Auth-Xpub") -}