uma

package
v0.3.1 Latest Latest
Warning

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

Go to latest
Published: Sep 21, 2023 License: Apache-2.0 Imports: 15 Imported by: 1

README

uma

The UMA protocol implementation for Go! See ../examples/uma-server for a sample implementation and check out the full documentation for more info.

Documentation

Overview

Copyright ©, 2023-present, Lightspark Group, Inc. - All Rights Reserved

Index

Constants

View Source
const MAJOR_VERSION = 0
View Source
const MINOR_VERSION = 1

Variables

View Source
var UmaProtocolVersion = fmt.Sprintf("%d.%d", MAJOR_VERSION, MINOR_VERSION)

Functions

func GenerateNonce

func GenerateNonce() (*string, error)

func GetSignedLnurlpRequestUrl

func GetSignedLnurlpRequestUrl(
	signingPrivateKey []byte,
	receiverAddress string,
	senderVaspDomain string,
	isSubjectToTravelRule bool,
	umaVersionOverride *string,
) (*url.URL, error)

GetSignedLnurlpRequestUrl Creates a signed uma request URL.

Args:

signingPrivateKey: the private key of the VASP that is sending the payment. This will be used to sign the request.
receiverAddress: the address of the receiver of the payment (i.e. $bob@vasp2).
senderVaspDomain: the domain of the VASP that is sending the payment. It will be used by the receiver to fetch the public keys of the sender.
isSubjectToTravelRule: whether the sending VASP is a financial institution that requires travel rule information.
umaVersionOverride: the version of the UMA protocol to use. If not specified, the latest version will be used.

func GetSupportedMajorVersions

func GetSupportedMajorVersions() map[int]struct{}

func GetSupportedMajorVersionsFromErrorResponseBody

func GetSupportedMajorVersionsFromErrorResponseBody(errorResponseBody []byte) ([]int, error)

func GetVaspDomainFromUmaAddress

func GetVaspDomainFromUmaAddress(umaAddress string) (string, error)

GetVaspDomainFromUmaAddress Gets the domain of the VASP from an uma address.

func IsUmaLnurlpQuery

func IsUmaLnurlpQuery(url url.URL) bool

IsUmaLnurlpQuery Checks if the given URL is a valid UMA request.

func IsVersionSupported

func IsVersionSupported(version string) bool

func SelectHighestSupportedVersion

func SelectHighestSupportedVersion(otherVaspSupportedMajorVersions []int) *string

func SelectLowerVersion

func SelectLowerVersion(version1String string, version2String string) (*string, error)

func VerifyPayReqSignature

func VerifyPayReqSignature(query *PayRequest, otherVaspPubKey []byte) error

VerifyPayReqSignature Verifies the signature on a uma pay request based on the public key of the VASP making the request.

Args:

query: the signed query to verify.
otherVaspPubKey: the bytes of the signing public key of the VASP making this request.

func VerifyUmaLnurlpQuerySignature

func VerifyUmaLnurlpQuerySignature(query *LnurlpRequest, otherVaspSigningPubKey []byte) error

VerifyUmaLnurlpQuerySignature Verifies the signature on an uma Lnurlp query based on the public key of the VASP making the request.

Args:

query: the signed query to verify.
otherVaspSigningPubKey: the public key of the VASP making this request in bytes.

func VerifyUmaLnurlpResponseSignature

func VerifyUmaLnurlpResponseSignature(response *LnurlpResponse, otherVaspSigningPubKey []byte) error

VerifyUmaLnurlpResponseSignature Verifies the signature on an uma Lnurlp response based on the public key of the VASP making the request.

Args:

response: the signed response to verify.
otherVaspSigningPubKey: the public key of the VASP making this request in bytes.

Types

type CompliancePayerData

type CompliancePayerData struct {
	// Utxos is the list of UTXOs of the sender's channels that might be used to fund the payment.
	Utxos *[]string `json:"utxos"`
	// NodePubKey is the public key of the sender's node if known.
	NodePubKey *string `json:"nodePubKey"`
	// KycStatus indicates whether VASP1 has KYC information about the sender.
	KycStatus KycStatus `json:"kycStatus"`
	// EncryptedTravelRuleInfo is the travel rule information of the sender. This is encrypted with the receiver's public encryption key.
	EncryptedTravelRuleInfo *string `json:"encryptedTravelRuleInfo"`
	// Signature is the base64-encoded signature of sha256(ReceiverAddress|Nonce|Timestamp).
	Signature          string `json:"signature"`
	SignatureNonce     string `json:"signatureNonce"`
	SignatureTimestamp int64  `json:"signatureTimestamp"`
	// UtxoCallback is the URL that the receiver will call to send UTXOs of the channel that the receiver used to receive the payment once it completes.
	UtxoCallback string `json:"utxoCallback"`
}

type Currency

type Currency struct {
	Code                string `json:"code"`
	Name                string `json:"name"`
	Symbol              string `json:"symbol"`
	MillisatoshiPerUnit int64  `json:"multiplier"`
	MinSendable         int64  `json:"minSendable"`
	MaxSendable         int64  `json:"maxSendable"`
}

type InMemoryPublicKeyCache

type InMemoryPublicKeyCache struct {
	// contains filtered or unexported fields
}

func NewInMemoryPublicKeyCache

func NewInMemoryPublicKeyCache() *InMemoryPublicKeyCache

func (*InMemoryPublicKeyCache) AddPublicKeyForVasp

func (c *InMemoryPublicKeyCache) AddPublicKeyForVasp(vaspDomain string, pubKey *PubKeyResponse)

func (*InMemoryPublicKeyCache) Clear

func (c *InMemoryPublicKeyCache) Clear()

func (*InMemoryPublicKeyCache) FetchPublicKeyForVasp

func (c *InMemoryPublicKeyCache) FetchPublicKeyForVasp(vaspDomain string) *PubKeyResponse

func (*InMemoryPublicKeyCache) RemovePublicKeyForVasp

func (c *InMemoryPublicKeyCache) RemovePublicKeyForVasp(vaspDomain string)

type KycStatus

type KycStatus int
const (
	KycStatusUnknown KycStatus = iota
	KycStatusNotVerified
	KycStatusPending
	KycStatusVerified
)

func (KycStatus) MarshalJSON

func (k KycStatus) MarshalJSON() ([]byte, error)

func (KycStatus) StringValue

func (k KycStatus) StringValue() string

func (*KycStatus) UnmarshalJSON

func (k *KycStatus) UnmarshalJSON(b []byte) error

type LightsparkClientUmaInvoiceCreator

type LightsparkClientUmaInvoiceCreator struct {
	LightsparkClient services.LightsparkClient
	// NodeId: the node ID of the receiver.
	NodeId string
	// ExpirySecs: the number of seconds until the invoice expires.
	ExpirySecs *int32
}

func (LightsparkClientUmaInvoiceCreator) CreateUmaInvoice

func (l LightsparkClientUmaInvoiceCreator) CreateUmaInvoice(amountMsats int64, metadata string) (*string, error)

type LnurlComplianceResponse

type LnurlComplianceResponse struct {
	// KycStatus indicates whether VASP2 has KYC information about the receiver.
	KycStatus KycStatus `json:"kycStatus"`
	// Signature is the base64-encoded signature of sha256(ReceiverAddress|Nonce|Timestamp).
	Signature string `json:"signature"`
	// Nonce is a random string that is used to prevent replay attacks.
	Nonce string `json:"signatureNonce"`
	// Timestamp is the unix timestamp of when the request was sent. Used in the signature.
	Timestamp int64 `json:"signatureTimestamp"`
	// IsSubjectToTravelRule indicates whether VASP2 is a financial institution that requires travel rule information.
	IsSubjectToTravelRule bool `json:"isSubjectToTravelRule"`
	// ReceiverIdentifier is the identifier of the receiver at VASP2.
	ReceiverIdentifier string `json:"receiverIdentifier"`
}

LnurlComplianceResponse is the `compliance` field of the LnurlpResponse.

type LnurlpRequest

type LnurlpRequest struct {
	// ReceiverAddress is the address of the user at VASP2 that is receiving the payment.
	ReceiverAddress string
	// Nonce is a random string that is used to prevent replay attacks.
	Nonce string
	// Signature is the base64-encoded signature of sha256(ReceiverAddress|Nonce|Timestamp).
	Signature string
	// IsSubjectToTravelRule indicates VASP1 is a financial institution that requires travel rule information.
	IsSubjectToTravelRule bool
	// VaspDomain is the domain of the VASP that is sending the payment. It will be used by VASP2 to fetch the public keys of VASP1.
	VaspDomain string
	// Timestamp is the unix timestamp of when the request was sent. Used in the signature.
	Timestamp time.Time
	// UmaVersion is the version of the UMA protocol that VASP1 prefers to use for this transaction. For the version
	// negotiation flow, see https://static.swimlanes.io/87f5d188e080cb8e0494e46f80f2ae74.png
	UmaVersion string
}

LnurlpRequest is the first request in the UMA protocol. It is sent by the VASP that is sending the payment to find out information about the receiver.

func ParseLnurlpRequest

func ParseLnurlpRequest(url url.URL) (*LnurlpRequest, error)

ParseLnurlpRequest Parse Parses the message into an LnurlpRequest object. Args:

url: the full URL of the uma request.

func (*LnurlpRequest) EncodeToUrl

func (q *LnurlpRequest) EncodeToUrl() (*url.URL, error)

type LnurlpResponse

type LnurlpResponse struct {
	Tag               string                  `json:"tag"`
	Callback          string                  `json:"callback"`
	MinSendable       int64                   `json:"minSendable"`
	MaxSendable       int64                   `json:"maxSendable"`
	EncodedMetadata   string                  `json:"metadata"`
	Currencies        []Currency              `json:"currencies"`
	RequiredPayerData PayerDataOptions        `json:"payerData"`
	Compliance        LnurlComplianceResponse `json:"compliance"`
	// UmaVersion is the version of the UMA protocol that VASP2 has chosen for this transaction based on its own support
	// and VASP1's specified preference in the LnurlpRequest. For the version negotiation flow, see
	// https://static.swimlanes.io/87f5d188e080cb8e0494e46f80f2ae74.png
	UmaVersion string `json:"umaVersion"`
}

LnurlpResponse is the response to the LnurlpRequest. It is sent by the VASP that is receiving the payment to provide information to the sender about the receiver.

func GetLnurlpResponse

func GetLnurlpResponse(
	request *LnurlpRequest,
	privateKeyBytes []byte,
	requiresTravelRuleInfo bool,
	callback string,
	encodedMetadata string,
	minSendableSats int64,
	maxSendableSats int64,
	payerDataOptions PayerDataOptions,
	currencyOptions []Currency,
	receiverKycStatus KycStatus,
) (*LnurlpResponse, error)

func ParseLnurlpResponse

func ParseLnurlpResponse(bytes []byte) (*LnurlpResponse, error)

type ParsedVersion

type ParsedVersion struct {
	Major int
	Minor int
}

func GetHighestSupportedVersionForMajorVersion

func GetHighestSupportedVersionForMajorVersion(majorVersion int) *ParsedVersion

func ParseVersion

func ParseVersion(version string) (*ParsedVersion, error)

func (*ParsedVersion) String

func (v *ParsedVersion) String() string

type PayReqResponse

type PayReqResponse struct {
	// EncodedInvoice is the BOLT11 invoice that the sender will pay.
	EncodedInvoice string `json:"pr"`
	// Routes is usually just an empty list from legacy LNURL, which was replaced by route hints in the BOLT11 invoice.
	Routes      []Route                   `json:"routes"`
	Compliance  PayReqResponseCompliance  `json:"compliance"`
	PaymentInfo PayReqResponsePaymentInfo `json:"paymentInfo"`
}

PayReqResponse is the response sent by the receiver to the sender to provide an invoice.

func GetPayReqResponse

func GetPayReqResponse(
	query *PayRequest,
	invoiceCreator UmaInvoiceCreator,
	metadata string,
	currencyCode string,
	conversionRate int64,
	receiverFeesMillisats int64,
	receiverChannelUtxos []string,
	receiverNodePubKey *string,
	utxoCallback string,
) (*PayReqResponse, error)

GetPayReqResponse Creates an uma pay request response with an encoded invoice.

Args:

	query: the uma pay request.
	invoiceCreator: the object that will create the invoice. In practice, this is usually a `services.LightsparkClient`.
	metadata: the metadata that will be added to the invoice's metadata hash field. Note that this should not include
	    the extra payer data. That will be appended automatically.
	currencyCode: the code of the currency that the receiver will receive for this payment.
	conversionRate: milli-satoshis per the smallest unit of the specified currency. This rate is committed to by the
    	receiving VASP until the invoice expires.
	receiverFeesMillisats: the fees charged (in millisats) by the receiving VASP to convert to the target currency.
	    This is separate from the conversion rate.
	receiverChannelUtxos: the list of UTXOs of the receiver's channels that might be used to fund the payment.
	receiverNodePubKey: If known, the public key of the receiver's node. If supported by the sending VASP's compliance provider,
        this will be used to pre-screen the receiver's UTXOs for compliance purposes.
	utxoCallback: the URL that the receiving VASP will call to send UTXOs of the channel that the receiver used to
    	receive the payment once it completes.

func ParsePayReqResponse

func ParsePayReqResponse(bytes []byte) (*PayReqResponse, error)

ParsePayReqResponse Parses the uma pay request response from a raw response body.

type PayReqResponseCompliance

type PayReqResponseCompliance struct {
	// NodePubKey is the public key of the receiver's node if known.
	NodePubKey *string `json:"nodePubKey"`
	// Utxos is a list of UTXOs of channels over which the receiver will likely receive the payment.
	Utxos []string `json:"utxos"`
	// UtxoCallback is the URL that the sender VASP will call to send UTXOs of the channel that the sender used to send the payment once it completes.
	UtxoCallback string `json:"utxoCallback"`
}

type PayReqResponsePaymentInfo

type PayReqResponsePaymentInfo struct {
	// CurrencyCode is the ISO 3-digit currency code that the receiver will receive for this payment.
	CurrencyCode string `json:"currencyCode"`
	// Multiplier is the conversion rate. It is the number of millisatoshis that the receiver will receive for 1 unit of the specified currency.
	Multiplier int64 `json:"multiplier"`
	// ExchangeFeesMillisatoshi is the fees charged (in millisats) by the receiving VASP for this transaction. This is
	// separate from the Multiplier.
	ExchangeFeesMillisatoshi int64 `json:"exchangeFeesMillisatoshi"`
}

type PayRequest

type PayRequest struct {
	// CurrencyCode is the ISO 3-digit currency code that the receiver will receive for this payment.
	CurrencyCode string `json:"currency"`
	// Amount is the amount that the receiver will receive for this payment in the smallest unit of the specified currency (i.e. cents for USD).
	Amount int64 `json:"amount"`
	// PayerData is the data that the sender will send to the receiver to identify themselves.
	PayerData PayerData `json:"payerData"`
}

PayRequest is the request sent by the sender to the receiver to retrieve an invoice.

func GetPayRequest

func GetPayRequest(
	receiverEncryptionPubKey []byte,
	sendingVaspPrivateKey []byte,
	currencyCode string,
	amount int64,
	payerIdentifier string,
	payerName *string,
	payerEmail *string,
	trInfo *string,
	payerKycStatus KycStatus,
	payerUtxos *[]string,
	payerNodePubKey *string,
	utxoCallback string,
) (*PayRequest, error)

GetPayRequest Creates a signed uma pay request.

Args:

	receiverEncryptionPubKey: the public key of the receiver that will be used to encrypt the travel rule information.
	sendingVaspPrivateKey: the private key of the VASP that is sending the payment. This will be used to sign the request.
	currencyCode: the code of the currency that the receiver will receive for this payment.
	amount: the amount of the payment in the smallest unit of the specified currency (i.e. cents for USD).
	payerIdentifier: the identifier of the sender. For example, $alice@vasp1.com
	payerName: the name of the sender (optional).
	payerEmail: the email of the sender (optional).
	trInfo: the travel rule information. This will be encrypted before sending to the receiver.
	isPayerKYCd: whether the sender is a KYC'd customer of the sending VASP.
	payerUtxos: the list of UTXOs of the sender's channels that might be used to fund the payment.
 	payerNodePubKey: If known, the public key of the sender's node. If supported by the receiving VASP's compliance provider,
        this will be used to pre-screen the sender's UTXOs for compliance purposes.
	utxoCallback: the URL that the receiver will call to send UTXOs of the channel that the receiver used to receive the payment once it completes.

func ParsePayRequest

func ParsePayRequest(bytes []byte) (*PayRequest, error)

func (*PayRequest) Encode

func (q *PayRequest) Encode() ([]byte, error)

type PayerData

type PayerData struct {
	Name       *string              `json:"name"`
	Email      *string              `json:"email"`
	Identifier string               `json:"identifier"`
	Compliance *CompliancePayerData `json:"compliance"`
}

type PayerDataOptions

type PayerDataOptions struct {
	NameRequired       bool
	EmailRequired      bool
	ComplianceRequired bool
}

func (*PayerDataOptions) MarshalJSON

func (p *PayerDataOptions) MarshalJSON() ([]byte, error)

func (*PayerDataOptions) UnmarshalJSON added in v0.3.1

func (p *PayerDataOptions) UnmarshalJSON(data []byte) error

type PubKeyResponse

type PubKeyResponse struct {
	// SigningPubKeyHex is used to verify signatures from a VASP. Hex-encoded byte array.
	SigningPubKeyHex string `json:"signingPubKey"`
	// EncryptionPubKeyHex is used to encrypt TR info sent to a VASP. Hex-encoded byte array.
	EncryptionPubKeyHex string `json:"encryptionPubKey"`
	// ExpirationTimestamp [Optional] Seconds since epoch at which these pub keys must be refreshed.
	// They can be safely cached until this expiration (or forever if null).
	ExpirationTimestamp *int64 `json:"expirationTimestamp"`
}

PubKeyResponse is sent from a VASP to another VASP to provide its public keys. It is the response to GET requests at `/.well-known/lnurlpubkey`.

func FetchPublicKeyForVasp

func FetchPublicKeyForVasp(vaspDomain string, cache PublicKeyCache) (*PubKeyResponse, error)

FetchPublicKeyForVasp fetches the public key for another VASP.

If the public key is not in the cache, it will be fetched from the VASP's domain. The public key will be cached for future use.

Args:

vaspDomain: the domain of the VASP.
cache: the PublicKeyCache cache to use. You can use the InMemoryPublicKeyCache struct, or implement your own persistent cache with any storage type.

func (*PubKeyResponse) EncryptionPubKey

func (r *PubKeyResponse) EncryptionPubKey() ([]byte, error)

func (*PubKeyResponse) SigningPubKey

func (r *PubKeyResponse) SigningPubKey() ([]byte, error)

type PublicKeyCache

type PublicKeyCache interface {
	// FetchPublicKeyForVasp fetches the public key entry for a VASP if in the cache, otherwise returns nil.
	FetchPublicKeyForVasp(vaspDomain string) *PubKeyResponse

	// AddPublicKeyForVasp adds a public key entry for a VASP to the cache.
	AddPublicKeyForVasp(vaspDomain string, pubKey *PubKeyResponse)

	// RemovePublicKeyForVasp removes a public key for a VASP from the cache.
	RemovePublicKeyForVasp(vaspDomain string)

	// Clear clears the cache.
	Clear()
}

PublicKeyCache is an interface for a cache of public keys for other VASPs.

Implementations of this interface should be thread-safe.

type Route

type Route struct {
	Pubkey string `json:"pubkey"`
	Path   []struct {
		Pubkey   string `json:"pubkey"`
		Fee      int64  `json:"fee"`
		Msatoshi int64  `json:"msatoshi"`
		Channel  string `json:"channel"`
	} `json:"path"`
}

type UmaInvoiceCreator

type UmaInvoiceCreator interface {
	CreateUmaInvoice(amountMsats int64, metadata string) (*string, error)
}

type UnsupportedVersionError

type UnsupportedVersionError struct {
	UnsupportedVersion     string `json:"unsupportedVersion"`
	SupportedMajorVersions []int  `json:"supportedMajorVersions"`
}

func (UnsupportedVersionError) Error

func (e UnsupportedVersionError) Error() string

type UtxoWithAmount

type UtxoWithAmount struct {
	// Utxo The utxo of the channel over which the payment went through in the format of <transaction_hash>:<output_index>.
	Utxo string `json:"utxo"`

	// Amount The amount of funds transferred in the payment in mSats.
	Amount int64 `json:"amountMsats"`
}

UtxoWithAmount is a pair of utxo and amount transferred over that corresponding channel. It can be used to register payment for KYT.

Jump to

Keyboard shortcuts

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