Documentation ¶
Overview ¶
Package minercraft is an unofficial Go version of Unwriter's Minercraft
If you have any suggestions or comments, please feel free to open an issue on this GitHub repository!
By TonicPow Inc (https://tonicpow.com)
Index ¶
- Constants
- type Client
- func (c *Client) AddMiner(miner Miner) error
- func (c *Client) BestQuote(feeCategory, feeType string) (*FeeQuoteResponse, error)
- func (c *Client) FastestQuote(ctx context.Context, timeout time.Duration) (*FeeQuoteResponse, error)
- func (c *Client) FeeQuote(miner *Miner) (*FeeQuoteResponse, error)
- func (c *Client) MinerByID(minerID string) *Miner
- func (c *Client) MinerByName(name string) *Miner
- func (c *Client) MinerUpdateToken(name, token string)
- func (c *Client) QueryTransaction(miner *Miner, txID string) (*QueryTransactionResponse, error)
- func (c *Client) RemoveMiner(miner *Miner) bool
- func (c *Client) SubmitTransaction(miner *Miner, tx *Transaction) (*SubmitTransactionResponse, error)
- type ClientOptions
- type ConflictedWith
- type FeePayload
- type FeeQuoteResponse
- type JSONEnvelope
- type Miner
- type QueryPayload
- type QueryTransactionResponse
- type RequestResponse
- type SubmissionPayload
- type SubmitTransactionResponse
- type Transaction
Examples ¶
Constants ¶
const ( // MinerTaal is the name of the known miner for "Taal" MinerTaal = "Taal" // MinerMempool is the name of the known miner for "Mempool" MinerMempool = "Mempool" // MinerMatterpool is the name of the known miner for "Matterpool" MinerMatterpool = "Matterpool" )
const ( // FeeTypeData is the key corresponding to the data rate FeeTypeData = "data" // FeeTypeStandard is the key corresponding to the standard rate FeeTypeStandard = "standard" // FeeCategoryMining is the category corresponding to the mining rate FeeCategoryMining = "mining" // FeeCategoryRelay is the category corresponding to the relay rate FeeCategoryRelay = "relay" )
const KnownMiners = `` /* 595-byte string literal not displayed */
KnownMiners is a pre-filled list of known miners Any pre-filled tokens are for free use only update your custom token with client.MinerUpdateToken("name", "token")
const (
// MerkleFormatTSC can be set when calling SubmitTransaction to request a MerkleProof in TSC format.
MerkleFormatTSC = "TSC"
)
const QueryTransactionFailure = "failure"
QueryTransactionFailure is on failure
const QueryTransactionInMempoolFailure = "Transaction in mempool but not yet in block"
QueryTransactionInMempoolFailure in mempool but not in a block yet
const QueryTransactionSuccess = "success"
QueryTransactionSuccess is on success
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Client ¶
type Client struct { Miners []*Miner // List of loaded miners Options *ClientOptions // Client options config // contains filtered or unexported fields }
Client is the parent struct that contains the miner clients and list of miners to use
func NewClient ¶
func NewClient(clientOptions *ClientOptions, customHTTPClient *http.Client, customMiners []*Miner) (client *Client, err error)
NewClient creates a new client for requests
clientOptions: inject custom client options on load customHTTPClient: use your own custom HTTP client customMiners: use your own custom list of miners
Example ¶
ExampleNewClient example using NewClient()
client, err := NewClient(nil, nil, nil) if err != nil { fmt.Printf("error occurred: %s", err.Error()) return } fmt.Printf("created new client with %d default miners", len(client.Miners))
Output: created new client with 3 default miners
func (*Client) AddMiner ¶
AddMiner will add a new miner to the list of miners
Example ¶
ExampleClient_AddMiner example using AddMiner()
client, err := NewClient(nil, nil, nil) if err != nil { fmt.Printf("error occurred: %s", err.Error()) return } // Add a miner if err = client.AddMiner(Miner{Name: testMinerName, URL: testMinerURL}); err != nil { fmt.Printf("error occurred: %s", err.Error()) return } // Get miner by name fmt.Printf("created new miner named: %s", client.MinerByName(testMinerName).Name)
Output: created new miner named: TestMiner
func (*Client) BestQuote ¶
func (c *Client) BestQuote(feeCategory, feeType string) (*FeeQuoteResponse, error)
BestQuote will check all known miners and compare rates, returning the best rate/quote
Note: this might return different results each time if miners have the same rates as it's a race condition on which results come back first
Example ¶
ExampleClient_BestQuote example using BestQuote()
// Create a client (using a test client vs NewClient()) client := newTestClient(&mockHTTPValidBestQuote{}) // Create a req _, err := client.BestQuote(FeeCategoryMining, FeeTypeData) if err != nil { fmt.Printf("error occurred: %s", err.Error()) return } // Note: cannot show response since the miner might be different each time fmt.Printf("got best quote!")
Output: got best quote!
func (*Client) FastestQuote ¶ added in v0.0.4
func (c *Client) FastestQuote(ctx context.Context, timeout time.Duration) (*FeeQuoteResponse, error)
FastestQuote will check all known miners and return the fastest quote response
Note: this might return different results each time if miners have the same rates as it's a race condition on which results come back first
Example ¶
ExampleClient_FastestQuote example using FastestQuote()
// Create a client (using a test client vs NewClient()) client := newTestClient(&mockHTTPValidFastestQuote{}) // Create a req _, err := client.FastestQuote(context.Background(), defaultFastQuoteTimeout) if err != nil { fmt.Printf("error occurred: %s", err.Error()) return } // Note: cannot show response since the miner might be different each time fmt.Printf("got fastest quote!")
Output: got fastest quote!
func (*Client) FeeQuote ¶
func (c *Client) FeeQuote(miner *Miner) (*FeeQuoteResponse, error)
FeeQuote will fire a Merchant API request to retrieve the fees from a given miner
This endpoint is used to get the different fees quoted by a miner. It returns a JSONEnvelope with a payload that contains the fees charged by a specific BSV miner. The purpose of the envelope is to ensure strict consistency in the message content for the purpose of signing responses.
Specs: https://github.com/bitcoin-sv-specs/brfc-merchantapi/tree/v1.2-beta#get-fee-quote
Example ¶
ExampleClient_FeeQuote example using FeeQuote()
// Create a client (using a test client vs NewClient()) client := newTestClient(&mockHTTPValidFeeQuote{}) // Create a req response, err := client.FeeQuote(client.MinerByName(MinerTaal)) if err != nil { fmt.Printf("error occurred: %s", err.Error()) return } fmt.Printf("got quote from: %s", response.Miner.Name)
Output: got quote from: Taal
func (*Client) MinerByID ¶
MinerByID will return a miner given a miner id
Example ¶
ExampleClient_MinerByID example using MinerByID()
client, err := NewClient(nil, nil, nil) if err != nil { fmt.Printf("error occurred: %s", err.Error()) return } // Add a miner if err = client.AddMiner(Miner{Name: testMinerName, MinerID: testMinerID, URL: testMinerURL}); err != nil { fmt.Printf("error occurred: %s", err.Error()) return } // Get miner by id fmt.Printf("created new miner named: %s", client.MinerByID(testMinerID).Name)
Output: created new miner named: TestMiner
func (*Client) MinerByName ¶
MinerByName will return a miner given a name
Example ¶
ExampleClient_MinerByName example using MinerByName()
client, err := NewClient(nil, nil, nil) if err != nil { fmt.Printf("error occurred: %s", err.Error()) return } // Add a miner if err = client.AddMiner(Miner{Name: testMinerName, URL: testMinerURL}); err != nil { fmt.Printf("error occurred: %s", err.Error()) return } // Get miner by name fmt.Printf("created new miner named: %s", client.MinerByName(testMinerName).Name)
Output: created new miner named: TestMiner
func (*Client) MinerUpdateToken ¶
MinerUpdateToken will find a miner by name and update the token
Example ¶
ExampleClient_MinerUpdateToken example using MinerUpdateToken()
client, err := NewClient(nil, nil, nil) if err != nil { fmt.Printf("error occurred: %s", err.Error()) return } // Update existing miner token client.MinerUpdateToken(MinerTaal, "9999") // Get miner by id fmt.Printf("miner token found: %s", client.MinerByName(MinerTaal).Token)
Output: miner token found: 9999
func (*Client) QueryTransaction ¶
func (c *Client) QueryTransaction(miner *Miner, txID string) (*QueryTransactionResponse, error)
QueryTransaction will fire a Merchant API request to check the status of a transaction
This endpoint is used to check the current status of a previously submitted transaction. It returns a JSONEnvelope with a payload that contains the transaction status. The purpose of the envelope is to ensure strict consistency in the message content for the purpose of signing responses.
Specs: https://github.com/bitcoin-sv-specs/brfc-merchantapi/tree/v1.2-beta#Query-transaction-status
Example ¶
ExampleClient_QueryTransaction example using QueryTransaction()
// Create a client (using a test client vs NewClient()) client := newTestClient(&mockHTTPValidQuery{}) // Create a req response, err := client.QueryTransaction(client.MinerByName(MinerTaal), testTx) if err != nil { fmt.Printf("error occurred: %s", err.Error()) return } fmt.Printf("got tx status %s from: %s", response.Query.ReturnResult, response.Miner.Name)
Output: got tx status success from: Taal
func (*Client) RemoveMiner ¶ added in v0.2.0
RemoveMiner will remove a miner from the list
Example ¶
ExampleClient_MinerUpdateToken example using RemoveMiner()
client, err := NewClient(nil, nil, nil) if err != nil { fmt.Printf("error occurred: %s", err.Error()) return } // Update existing miner token client.RemoveMiner(client.MinerByName(MinerTaal)) // Show response fmt.Printf("total miners: %d", len(client.Miners))
Output: total miners: 2
func (*Client) SubmitTransaction ¶
func (c *Client) SubmitTransaction(miner *Miner, tx *Transaction) (*SubmitTransactionResponse, error)
SubmitTransaction will fire a Merchant API request to submit a given transaction
This endpoint is used to send a raw transaction to a miner for inclusion in the next block that the miner creates. It returns a JSONEnvelope with a payload that contains the response to the transaction submission. The purpose of the envelope is to ensure strict consistency in the message content for the purpose of signing responses.
Specs: https://github.com/bitcoin-sv-specs/brfc-merchantapi/tree/v1.2-beta#Submit-transaction
Example ¶
ExampleClient_SubmitTransaction example using SubmitTransaction()
// Create a client (using a test client vs NewClient()) client := newTestClient(&mockHTTPValidSubmission{}) tx := &Transaction{RawTx: submitTestExampleTx} // Create a req response, err := client.SubmitTransaction(client.MinerByName(MinerTaal), tx) if err != nil { fmt.Printf("error occurred: %s", err.Error()) return } fmt.Printf("submitted tx to: %s", response.Miner.Name)
Output: submitted tx to: Taal
type ClientOptions ¶
type ClientOptions struct { BackOffExponentFactor float64 `json:"back_off_exponent_factor"` BackOffInitialTimeout time.Duration `json:"back_off_initial_timeout"` BackOffMaximumJitterInterval time.Duration `json:"back_off_maximum_jitter_interval"` BackOffMaxTimeout time.Duration `json:"back_off_max_timeout"` DialerKeepAlive time.Duration `json:"dialer_keep_alive"` DialerTimeout time.Duration `json:"dialer_timeout"` RequestRetryCount int `json:"request_retry_count"` RequestTimeout time.Duration `json:"request_timeout"` TransportExpectContinueTimeout time.Duration `json:"transport_expect_continue_timeout"` TransportIdleTimeout time.Duration `json:"transport_idle_timeout"` TransportMaxIdleConnections int `json:"transport_max_idle_connections"` TransportTLSHandshakeTimeout time.Duration `json:"transport_tls_handshake_timeout"` UserAgent string `json:"user_agent"` }
ClientOptions holds all the configuration for connection, dialer and transport
func DefaultClientOptions ¶
func DefaultClientOptions() (clientOptions *ClientOptions)
DefaultClientOptions will return a ClientOptions struct with the default settings. Useful for starting with the default and then modifying as needed
Example ¶
ExampleDefaultClientOptions example using DefaultClientOptions()
options := DefaultClientOptions() options.UserAgent = "Custom UserAgent v1.0" client, err := NewClient(options, nil, nil) if err != nil { fmt.Printf("error occurred: %s", err.Error()) return } fmt.Printf("created new client with user agent: %s", client.Options.UserAgent)
Output: created new client with user agent: Custom UserAgent v1.0
type ConflictedWith ¶ added in v0.2.6
type ConflictedWith struct { TxID string `json:"txid"` Size int `json:"size"` Hex string `json:"hex"` }
ConflictedWith contains the information about the transactions that conflict with the transaction submitted to mAPI. A conflict could arise if multiple transactions attempt to spend the same UTXO (double spend).
type FeePayload ¶
type FeePayload struct { APIVersion string `json:"apiVersion"` Timestamp string `json:"timestamp"` ExpirationTime string `json:"expiryTime"` MinerID string `json:"minerId"` CurrentHighestBlockHash string `json:"currentHighestBlockHash"` CurrentHighestBlockHeight uint64 `json:"currentHighestBlockHeight"` MinerReputation interface{} `json:"minerReputation"` // Not sure what this value is Fees []*bt.Fee `json:"fees"` }
FeePayload is the unmarshalled version of the payload envelope
func (*FeePayload) CalculateFee ¶
func (f *FeePayload) CalculateFee(feeCategory, feeType string, txBytes uint64) (uint64, error)
CalculateFee will return the fee for the given txBytes Type: "FeeTypeData" or "FeeTypeStandard" Category: "FeeCategoryMining" or "FeeCategoryRelay"
If no fee is found or fee is 0, returns 1 & error
Example ¶
ExampleFeePayload_CalculateFee example using CalculateFee()
// Create a client (using a test client vs NewClient()) client := newTestClient(&mockHTTPValidBestQuote{}) // Create a req response, err := client.BestQuote(FeeCategoryMining, FeeTypeData) if err != nil { fmt.Printf("error occurred: %s", err.Error()) return } // Calculate fee for tx var fee uint64 fee, err = response.Quote.CalculateFee(FeeCategoryMining, FeeTypeData, 1000) if err != nil { fmt.Printf("error occurred: %s", err.Error()) return } // Note: cannot show response since the miner might be different each time fmt.Printf("got best quote and fee for 1000 byte tx is: %d", fee)
Output: got best quote and fee for 1000 byte tx is: 420
func (*FeePayload) GetFee ¶ added in v0.2.9
func (f *FeePayload) GetFee(feeType string) *bt.Fee
GetFee will return the fee associated to the type (standard, data)
Example ¶
ExampleFeePayload_GetFee example using GetFee()
// Create a client (using a test client vs NewClient()) client := newTestClient(&mockHTTPValidBestQuote{}) // Create a req response, err := client.BestQuote(FeeCategoryMining, FeeTypeData) if err != nil { fmt.Printf("error occurred: %s", err.Error()) return } // Get the fee fee := response.Quote.GetFee(FeeTypeStandard) fmt.Printf( "got best quote and fee for %d byte tx is %d sats", fee.MiningFee.Bytes, fee.MiningFee.Satoshis, )
Output: got best quote and fee for 1000 byte tx is 500 sats
type FeeQuoteResponse ¶
type FeeQuoteResponse struct { JSONEnvelope Quote *FeePayload `json:"quote"` // Custom field for unmarshalled payload data }
FeeQuoteResponse is the raw response from the Merchant API request
Specs: https://github.com/bitcoin-sv-specs/brfc-merchantapi/tree/v1.2-beta#get-fee-quote
type JSONEnvelope ¶
type JSONEnvelope struct { Miner *Miner `json:"miner"` // Custom field for our internal Miner configuration Validated bool `json:"validated"` // Custom field if the signature has been validated Payload string `json:"payload"` Signature string `json:"signature"` PublicKey string `json:"publicKey"` Encoding string `json:"encoding"` MimeType string `json:"mimetype"` }
JSONEnvelope is a standard response from the Merchant API requests
Standard for serializing a JSON document in order to have consistency when ECDSA signing the document. Any changes to a document being signed and verified, however minor they may be, will cause the signature verification to fail since the document will be converted into a string before being (hashed and then) signed. With JSON documents, the format permits changes to be made without compromising the validity of the format (e.g. extra spaces, carriage returns, etc.).
This spec describes a technique to ensure consistency of the data being signed by encapsulating the JSON data as a string in parent JSON object. That way, however the JSON is marshaled, the first element in the parent JSON, the payload, would remain the same and be signed/verified the way it is.
Specs: https://github.com/bitcoin-sv-specs/brfc-misc/tree/master/jsonenvelope
type Miner ¶
type Miner struct { MinerID string `json:"miner_id,omitempty"` Name string `json:"name,omitempty"` Token string `json:"token,omitempty"` URL string `json:"url"` }
Miner is a configuration per miner, including connection url, auth token, etc
type QueryPayload ¶
type QueryPayload struct { APIVersion string `json:"apiVersion"` Timestamp string `json:"timestamp"` TxID string `json:"txid"` ReturnResult string `json:"returnResult"` ResultDescription string `json:"resultDescription"` BlockHash string `json:"blockHash"` BlockHeight int64 `json:"blockHeight"` MinerID string `json:"minerId"` Confirmations int64 `json:"confirmations"` TxSecondMempoolExpiry int64 `json:"txSecondMempoolExpiry"` }
QueryPayload is the unmarshalled version of the payload envelope
type QueryTransactionResponse ¶
type QueryTransactionResponse struct { JSONEnvelope Query *QueryPayload `json:"query"` // Custom field for unmarshalled payload data }
QueryTransactionResponse is the raw response from the Merchant API request
Specs: https://github.com/bitcoin-sv-specs/brfc-merchantapi/tree/v1.2-beta#Query-transaction-status
type RequestResponse ¶
type RequestResponse struct { BodyContents []byte `json:"body_contents"` // Raw body response Error error `json:"error"` // If an error occurs Method string `json:"method"` // Method is the HTTP method used PostData string `json:"post_data"` // PostData is the post data submitted if POST/PUT request StatusCode int `json:"status_code"` // StatusCode is the last code from the request URL string `json:"url"` // URL is used for the request }
RequestResponse is the response from a request
type SubmissionPayload ¶
type SubmissionPayload struct { APIVersion string `json:"apiVersion"` Timestamp string `json:"timestamp"` TxID string `json:"txid"` ReturnResult string `json:"returnResult"` ResultDescription string `json:"resultDescription"` MinerID string `json:"minerId"` CurrentHighestBlockHash string `json:"currentHighestBlockHash"` ConflictedWith []*ConflictedWith `json:"conflictedWith"` CurrentHighestBlockHeight int64 `json:"currentHighestBlockHeight"` TxSecondMempoolExpiry int64 `json:"txSecondMempoolExpiry"` }
SubmissionPayload is the unmarshalled version of the payload envelope
type SubmitTransactionResponse ¶
type SubmitTransactionResponse struct { JSONEnvelope Results *SubmissionPayload `json:"results"` // Custom field for unmarshalled payload data }
SubmitTransactionResponse is the raw response from the Merchant API request
Specs: https://github.com/bitcoin-sv-specs/brfc-merchantapi/tree/v1.2-beta#Submit-transaction
type Transaction ¶
type Transaction struct { RawTx string `json:"rawtx"` CallBackURL string `json:"callBackUrl,omitempty"` CallBackToken string `json:"callBackToken,omitempty"` MerkleFormat string `json:"merkleFormat,omitempty"` CallBackEncryption string `json:"callBackEncryption,omitempty"` MerkleProof bool `json:"merkleProof,omitempty"` DsCheck bool `json:"dsCheck,omitempty"` }
Transaction is the body contents in the "submit transaction" request