dpp

package module
v0.1.11 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 4, 2022 License: ISC Imports: 10 Imported by: 13

README

DPP - Direct Payment Protocol

Release Build Status Report Go Sponsor Donate

DPP is a basic reference implementation of a Payment Protocol Server implementing the proposed BIP-270 payment flow.

This is written in go and integrates with a wallet running the Payment Protocol PayD Interface.

Exploring Endpoints

To explore the endpoints and functionality, run the server using go run cmd/rest-server/main.go and navigate to Swagger where the endpoints and their models are described in detail.

Configuring DPP

The server has a series of environment variables that allow you to configure the behaviours and integrations of the server. Values can also be passed at build time to provide information such as build information, region, version etc.

Server
Key Description Default
SERVER_PORT Port which this server should use :8445
SERVER_HOST Host name under which this server is found dpp
SERVER_SWAGGER_ENABLED If set to true we will expose an endpoint hosting the Swagger docs true
SERVER_SWAGGER_HOST Sets the base url for swagger ui calls localhost:8445
Environment / Deployment Info
Key Description Default
ENV_ENVIRONMENT What enviornment we are running in, for example 'production' dev
ENV_REGION Region we are running in, for example 'eu-west-1' local
ENV_COMMIT Commit hash for the current build test
ENV_VERSION Semver tag for the current build, for example v1.0.0 v0.0.0
ENV_BUILDDATE Date the code was build Current UTC time
ENV_BITCOIN_NETWORK What bitcoin network we are connecting to (mainnet, testnet, stn, regtest) regtest
Logging
Key Description Default
LOG_LEVEL Level of logging we want within the server (debug, error, warn, info) info
PayD Wallet
Key Description Default
PAYD_HOST Host for the wallet we are connecting to payd
PAYD_PORT Port the PayD wallet is listening on :8443
PAYD_SECURE If true the DPP server will validate the wallet TLS certs false
PAYD_NOOP If true we will use a dummy data store in place of payd true

Working with DPP

There are a set of makefile commands listed under the Makefile which give some useful shortcuts when working with the repo.

Some of the more common commands are listed below:

make pre-commit - ensures dependencies are up to date and runs linter and unit tests.

make build-image - builds a local docker image, useful when testing dpp in docker.

make run-compose - runs DPP in compose, a reference PayD wallet will be added to compose soon NOTE the above command will need ran first.

Rebuild on code change

You can also add an optional docker-compose.dev.yml file (this is not committed) where you can safely overwrite values or add other services without impacting the main compose file.

If you add this file, you can run it with make run-compose-dev.

The file I use has a watcher which means it auto rebuilds the image on code change and ensures compose is always up to date, this full file is shown below:

version: "3.7"

services:
  dpp:
    image: theflyingcodr/go-watcher:1.15.8
    environment:
      GO111MODULE: "on"
      GOFLAGS: "-mod=vendor"
      DB_DSN: "file:data/wallet.db?cache=shared&_foreign_keys=true;"
      DB_SCHEMA_PATH: "data/sqlite/migrations"
    command: watcher -run github.com/libsv/go-dpp/cmd/rest-server/ -watch github.com/libsv/go-dpp
    working_dir: /go/src/github.com/libsv/go-dpp
    volumes:
      - ~/git/libsv/go-dpp:/go/src/github.com/libsv/go-dpp

CI / CD

We use github actions to test and build the code.

If a new release is required, after your PR is approved and code added to master, simply add a new semver tag and a GitHub action will build and publish your code as well as create a GitHub release.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Destinations

type Destinations struct {
	AncestryRequired bool         `json:"ancestryRequired"`
	Network          string       `json:"network"`
	Outputs          []Output     `json:"outputs"`
	Fees             *bt.FeeQuote `json:"fees"`
	CreatedAt        time.Time    `json:"createdAt"`
	ExpiresAt        time.Time    `json:"expiresAt"`
}

Destinations message containing outputs and their fees.

type Merchant

type Merchant struct {
	// AvatarURL displays a canonical url to a merchants avatar.
	AvatarURL string `json:"avatar" example:"http://url.com"`
	// Name is a human readable string identifying the merchant.
	Name string `json:"name" example:"merchant 1"`
	// Email can be sued to contact the merchant about this transaction.
	Email string `json:"email" example:"merchant@m.com"`
	// Address is the merchants store / head office address.
	Address string `json:"address" example:"1 the street, the town, B1 1AA"`
	// ExtendedData can be supplied if the merchant wishes to send some arbitrary data back to the wallet.
	ExtendedData map[string]interface{} `json:"extendedData,omitempty"`
}

Merchant to be displayed to the user.

type Output

type Output struct {
	// Amount is the number of satoshis to be paid.
	Amount uint64 `json:"amount" example:"100000"`
	// Script is a locking script where payment should be sent, formatted as a hexadecimal string.
	LockingScript *bscript.Script `json:"script" swaggertype:"primitive,string" example:"76a91455b61be43392125d127f1780fb038437cd67ef9c88ac"`
	// Description, an optional description such as "tip" or "sales tax". Maximum length is 100 chars.
	Description string `json:"description" example:"paymentReference 123456"`
}

Output message used in BIP270. See https://github.com/moneybutton/bips/blob/master/bip-0270.mediawiki#output

type Payment

type Payment struct {
	// MerchantData is copied from PaymentDetails.merchantData.
	// Payment hosts may use invoice numbers or any other data they require to match Payments to PaymentRequests.
	// Note that malicious clients may modify the merchantData, so should be authenticated
	// in some way (for example, signed with a payment host-only key).
	// Maximum length is 10000 characters.
	MerchantData Merchant `json:"merchantData"`
	// RefundTo is a paymail to send a refund to should a refund be necessary.
	// Maximum length is 100 characters
	RefundTo *string `json:"refundTo"  swaggertype:"primitive,string" example:"me@paymail.com"`
	// Memo is a plain-text note from the customer to the payment host.
	Memo string `json:"memo" example:"for invoice 123456"`
	// Ancestry which contains the details of previous transaction and Merkle proof of each input UTXO.
	// Should be available if AncestryRequired is set to true in the paymentRequest.
	// See https://tsc.bitcoinassociation.net/standards/spv-envelope/
	Ancestry *string `json:"ancestry"`
	// RawTX should be sent if AncestryRequired is set to false in the payment request.
	RawTx *string `json:"rawTx"`
	// ProofCallbacks are optional and can be supplied when the sender wants to receive
	// a merkleproof for the transaction they are submitting as part of the SPV Envelope.
	//
	// This is especially useful if they are receiving change and means when they use it
	// as an input, they can provide the merkle proof.
	ProofCallbacks map[string]ProofCallback `json:"proofCallbacks"`
}

Payment is a Payment message used in BIP270. See https://github.com/moneybutton/bips/blob/master/bip-0270.mediawiki#payment

func (Payment) Validate

func (p Payment) Validate() error

Validate will ensure the users request is correct.

type PaymentACK

type PaymentACK struct {
	ID          string           `json:"id"`
	TxID        string           `json:"tx_id"`
	Memo        string           `json:"memo"`
	PeerChannel *PeerChannelData `json:"peer_channel"`
	// A number indicating why the transaction was not accepted. 0 or undefined indicates no error.
	// A 1 or any other positive integer indicates an error. The errors are left undefined for now;
	// it is recommended only to use “1” and to fill the memo with a textual explanation about why
	// the transaction was not accepted until further numbers are defined and standardised.
	Error int `json:"error,omitempty"`
}

PaymentACK message used in BIP270. See https://github.com/moneybutton/bips/blob/master/bip-0270.mediawiki#paymentack

type PaymentCreateArgs

type PaymentCreateArgs struct {
	PaymentID string `param:"paymentID"`
}

PaymentCreateArgs identifies the paymentID used for the payment.

func (PaymentCreateArgs) Validate

func (p PaymentCreateArgs) Validate() error

Validate will ensure that the PaymentCreateArgs are supplied and correct.

type PaymentDestinations

type PaymentDestinations struct {
	Outputs []Output `json:"outputs"`
}

PaymentDestinations contains the supported destinations by this DPP server.

type PaymentRequest

type PaymentRequest struct {
	// Network  Always set to "bitcoin" (but seems to be set to 'bitcoin-sv'
	// outside bip270 spec, see https://handcash.github.io/handcash-merchant-integration/#/merchant-payments)
	// {enum: bitcoin, bitcoin-sv, test}
	// Required.
	Network string `json:"network" example:"mainnet" enums:"mainnet,testnet,stn,regtest"`
	// AncestryRequired if true will expect the sender to submit an ancestry in the payment request, otherwise
	// a rawTx will be required.
	AncestryRequired bool `json:"ancestryRequired" example:"true"`
	// Destinations contains supported payment destinations by the merchant and dpp server, initial P2PKH outputs but can be extended.
	// Required.
	Destinations PaymentDestinations `json:"destinations"`
	// CreationTimestamp Unix timestamp (seconds since 1-Jan-1970 UTC) when the PaymentRequest was created.
	// Required.
	CreationTimestamp time.Time `json:"creationTimestamp" swaggertype:"primitive,string" example:"2019-10-12T07:20:50.52Z"`
	// ExpirationTimestamp Unix timestamp (UTC) after which the PaymentRequest should be considered invalid.
	// Optional.
	ExpirationTimestamp time.Time `json:"expirationTimestamp" swaggertype:"primitive,string" example:"2019-10-12T07:20:50.52Z"`
	// PaymentURL secure HTTPS location where a Payment message (see below) will be sent to obtain a PaymentACK.
	// Maximum length is 4000 characters
	PaymentURL string `json:"paymentUrl" example:"https://localhost:3443/api/v1/payment/123456"`
	// Memo Optional note that should be displayed to the customer, explaining what this PaymentRequest is for.
	// Maximum length is 50 characters.
	Memo string `json:"memo" example:"invoice number 123456"`
	// MerchantData contains arbitrary data that may be used by the payment host to identify the PaymentRequest.
	// May be omitted if the payment host does not need to associate Payments with PaymentRequest
	// or if they associate each PaymentRequest with a separate payment address.
	// Maximum length is 10000 characters.
	MerchantData *Merchant `json:"merchantData,omitempty"`
	// FeeRate defines the amount of fees a users wallet should add to the payment
	// when submitting their final payments.
	FeeRate *bt.FeeQuote `json:"fees"`
}

PaymentRequest message used in BIP270. See https://github.com/moneybutton/bips/blob/master/bip-0270.mediawiki#paymentrequest

type PaymentRequestArgs

type PaymentRequestArgs struct {
	// PaymentID is an identifier for an invoice.
	PaymentID string `param:"paymentID"`
}

PaymentRequestArgs are request arguments that can be passed to the service.

type PaymentRequestReader

type PaymentRequestReader interface {
	PaymentRequest(ctx context.Context, args PaymentRequestArgs) (*PaymentRequest, error)
}

PaymentRequestReader will return a new payment request.

type PaymentRequestService

type PaymentRequestService interface {
	PaymentRequestReader
}

PaymentRequestService can be implemented to enforce business rules and process in order to fulfil a PaymentRequest.

type PaymentService

type PaymentService interface {
	PaymentCreate(ctx context.Context, args PaymentCreateArgs, req Payment) (*PaymentACK, error)
}

PaymentService enforces business rules when creating payments.

type PaymentWriter

type PaymentWriter interface {
	PaymentCreate(ctx context.Context, args PaymentCreateArgs, req Payment) (*PaymentACK, error)
}

PaymentWriter will write a payment to a data store.

type PeerChannelData

type PeerChannelData struct {
	Host      string `json:"host"`
	Path      string `json:"path"`
	ChannelID string `json:"channel_id"`
	Token     string `json:"token"`
}

PeerChannelData holds peer channel information for subscribing to and reading from a peer channel.

type ProofCallback

type ProofCallback struct {
	Token string `json:"token"`
}

ProofCallback is used by a payee to request a merkle proof is sent to them as proof of acceptance of the tx they have provided in the ancestry.

type ProofCreateArgs

type ProofCreateArgs struct {
	// TxID will be used to validate the proof envelope.
	TxID             string `json:"txId" param:"txid"`
	PaymentReference string `query:"i"`
}

ProofCreateArgs are used to create a proof.

type ProofWrapper

type ProofWrapper struct {
	CallbackPayload *bc.MerkleProof `json:"callbackPayload"`
	BlockHash       string          `json:"blockHash"`
	BlockHeight     uint32          `json:"blockHeight"`
	CallbackTxID    string          `json:"callbackTxID"`
	CallbackReason  string          `json:"callbackReason"`
}

ProofWrapper represents a mapi callback payload for a merkleproof. mAPI returns proofs in a JSONEnvelope with a payload. This represents the Payload format which contains a parent object with tx meta and a nested object which is the TSC format merkleProof.

func (ProofWrapper) Validate

func (p ProofWrapper) Validate(args ProofCreateArgs) error

Validate will ensure the ProofWrapper is valid.

type ProofsService

type ProofsService interface {
	// Create will store a JSONEnvelope that contains a merkleproof. The envelope should
	// be validated to not be tampered with and the Envelope should be opened to check the payload
	// is indeed a MerkleProof.
	Create(ctx context.Context, args ProofCreateArgs, req envelope.JSONEnvelope) error
}

ProofsService enforces business rules and validation when handling merkle proofs.

type ProofsWriter

type ProofsWriter interface {
	// ProofCreate can be used to persist a merkle proof in TSC format.
	ProofCreate(ctx context.Context, args ProofCreateArgs, req envelope.JSONEnvelope) error
}

ProofsWriter is used to persist a proof to a data store.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL