mirror of
https://github.com/aljazceru/ark.git
synced 2025-12-18 12:44:19 +01:00
Rename folders (#97)
* Rename arkd folder & drop cli * Rename ark cli folder & update docs * Update readme * Fix * scripts: add build-all * Add target to build cli for all platforms * Update build scripts --------- Co-authored-by: tiero <3596602+tiero@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
0d8c7bffb2
commit
dc00d60585
129
server/internal/core/domain/payment.go
Normal file
129
server/internal/core/domain/payment.go
Normal file
@@ -0,0 +1,129 @@
|
||||
package domain
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"hash"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
const dustAmount = 450
|
||||
|
||||
type Payment struct {
|
||||
Id string
|
||||
Inputs []Vtxo
|
||||
Receivers []Receiver
|
||||
}
|
||||
|
||||
func NewPayment(inputs []Vtxo) (*Payment, error) {
|
||||
p := &Payment{
|
||||
Id: uuid.New().String(),
|
||||
Inputs: inputs,
|
||||
}
|
||||
if err := p.validate(true); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (p *Payment) AddReceivers(receivers []Receiver) (err error) {
|
||||
if p.Receivers == nil {
|
||||
p.Receivers = make([]Receiver, 0)
|
||||
}
|
||||
p.Receivers = append(p.Receivers, receivers...)
|
||||
defer func() {
|
||||
if err != nil {
|
||||
p.Receivers = p.Receivers[:len(p.Receivers)-len(receivers)]
|
||||
}
|
||||
}()
|
||||
err = p.validate(false)
|
||||
return
|
||||
}
|
||||
|
||||
func (p Payment) TotalInputAmount() uint64 {
|
||||
tot := uint64(0)
|
||||
for _, in := range p.Inputs {
|
||||
tot += in.Amount
|
||||
}
|
||||
return tot
|
||||
}
|
||||
|
||||
func (p Payment) TotalOutputAmount() uint64 {
|
||||
tot := uint64(0)
|
||||
for _, r := range p.Receivers {
|
||||
tot += r.Amount
|
||||
}
|
||||
return tot
|
||||
}
|
||||
|
||||
func (p Payment) validate(ignoreOuts bool) error {
|
||||
if len(p.Id) <= 0 {
|
||||
return fmt.Errorf("missing id")
|
||||
}
|
||||
if len(p.Inputs) <= 0 {
|
||||
return fmt.Errorf("missing inputs")
|
||||
}
|
||||
if ignoreOuts {
|
||||
return nil
|
||||
}
|
||||
if len(p.Receivers) <= 0 {
|
||||
return fmt.Errorf("missing outputs")
|
||||
}
|
||||
// Check that input and output and output amounts match.
|
||||
inAmount := p.TotalInputAmount()
|
||||
outAmount := uint64(0)
|
||||
for _, r := range p.Receivers {
|
||||
if len(r.OnchainAddress) <= 0 && len(r.Pubkey) <= 0 {
|
||||
return fmt.Errorf("missing receiver destination")
|
||||
}
|
||||
if r.Amount < dustAmount {
|
||||
return fmt.Errorf("receiver amount must be greater than dust")
|
||||
}
|
||||
outAmount += r.Amount
|
||||
}
|
||||
if inAmount != outAmount {
|
||||
return fmt.Errorf("input and output amounts mismatch")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type VtxoKey struct {
|
||||
Txid string
|
||||
VOut uint32
|
||||
}
|
||||
|
||||
func (k VtxoKey) Hash() string {
|
||||
calcHash := func(buf []byte, hasher hash.Hash) []byte {
|
||||
_, _ = hasher.Write(buf)
|
||||
return hasher.Sum(nil)
|
||||
}
|
||||
|
||||
hash160 := func(buf []byte) []byte {
|
||||
return calcHash(calcHash(buf, sha256.New()), sha256.New())
|
||||
}
|
||||
|
||||
buf, _ := hex.DecodeString(k.Txid)
|
||||
buf = append(buf, byte(k.VOut))
|
||||
return hex.EncodeToString(hash160(buf))
|
||||
}
|
||||
|
||||
type Receiver struct {
|
||||
Pubkey string
|
||||
Amount uint64
|
||||
OnchainAddress string
|
||||
}
|
||||
|
||||
func (r Receiver) IsOnchain() bool {
|
||||
return len(r.OnchainAddress) > 0
|
||||
}
|
||||
|
||||
type Vtxo struct {
|
||||
VtxoKey
|
||||
Receiver
|
||||
PoolTx string
|
||||
Spent bool
|
||||
Redeemed bool
|
||||
Swept bool
|
||||
}
|
||||
Reference in New Issue
Block a user