From d5c8af9172e4488fbc95acca688bf9f18110fd1f Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Fri, 17 Jan 2020 17:10:38 -0800 Subject: [PATCH] Initial Tool Commit --- LICENSE | 2 +- README.md | 1 + bisqcontract.go | 103 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 bisqcontract.go diff --git a/LICENSE b/LICENSE index d449d3e..43ca71f 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) +Copyright (c) 2020 Open Privacy Research Society Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 585b47b..ef7a648 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,3 @@ # bisq-contract-tool +A tiny WIP tool for managing archives of Bisq contracts. \ No newline at end of file diff --git a/bisqcontract.go b/bisqcontract.go new file mode 100644 index 0000000..3a117e3 --- /dev/null +++ b/bisqcontract.go @@ -0,0 +1,103 @@ +package main + +import ( + "crypto/sha256" + "encoding/json" + "fmt" + "io/ioutil" + "math" + "os" + "time" +) + +type Offer struct { + ID string `json:"id"` + Date int `json:"date"` + OwnerNodeAddress NodeAddress `json:"ownerNodeAddress"` + Direction string `json:"direction"` + Price int `json:"price"` + MarketPriceMargin float64 `json:"marketPriceMargin"` + UseMarketBasedPrice bool `json:"useMarketBasedPrice"` + Amount int64 `json:"amount"` + MinAmount int64 `json:"minAmount"` + BaseCurrencyCode string `json:"baseCurrencyCode"` + CounterCurrencyCode string `json:"counterCurrencyCode"` + ArbitratorNodeAddresses []NodeAddress `json:"arbitratorNodeAddresses"` + MediatorNodeAddress []NodeAddress `json:"mediatorNodeAddresses"` + PaymentMethodId string `json:"paymentMethodId"` + MakerPaymentAccountId string `json:"makerPaymentAccountId"` + OfferFeePaymentTxId string `json:"offerFeePaymentTxId"` + VersionNR string `json:"versionNr"` + BlockHeightAtOfferCreation int `json:"blockHeightAtOfferCreation"` + TxFee int `json:"txFee"` + MakerFee int `json:"makerFee"` + IsCurrencyForMakerFeeBtc bool `json:"isCurrencyForMakerFeeBtc"` + BuyerSecurityDeposit int `json:"buyerSecurityDeposit"` + SellerSecurityDeposit int `json:"sellerSecurityDeposit"` + MaxTradeLimit int `json:"maxTradeLimit"` + MaxTradePeriod int `json:"maxTradePeriod"` + UseAutoClose bool `json:"useAutoClose"` + UseReOpenAfterAutoClose bool `json:"useReOpenAfterAutoClose"` + LowerClosePrice int `json:"lowerClosePrice"` + UpperClosePrice int `json:"upperClosePrice"` + IsPrivateOffer bool `json:"isPrivateOffer"` + ExtraDataMap map[string]string `json:"extraDataMap"` + ProtocolVersion int `json:"protocolVersion"` +} + +type NodeAddress struct { + HostName string `json:"hostName"` + Port int `json:"port"` +} + +type AccountPayload struct { + Address string `json:"address"` + PaymentMethodId string `json:"paymentMethodId"` + ID string `json:"id"` + MaxTradePeriod int `json:"maxTradePeriod"` +} + +type BisqContract struct { + OfferPayload Offer `json:"offerPayload"` + TradeAmount int `json:"tradeAmount"` + TradePrice int `json:"tradePrice"` + TakerFeeTXID string `json:"takerFeeTxID"` + BuyerNodeAddress NodeAddress `json:"buyerNodeAddress"` + SellerNodeAddress NodeAddress `json:"sellerNodeAddress"` + MediatorNodeAddress NodeAddress `json:"mediatorNodeAddress"` + IsBuyerMakerAndSellerTaker bool `json:"isBuyerMakerAndSellerTaker"` + MakerAccountId string `json:"makerAccountId"` + TakerAccountId string `json:"takerAccountId"` + MakerPaymentAccountPayload AccountPayload `json:"makerPaymentAccountPayload"` + TakerPaymentAccountPayload AccountPayload `json:"takerPaymentAccountPayload"` + MakerPayoutAddressString string `json:"makerPayoutAddressString"` + TakerPayoutAddressString string `json:"takerPayoutAddressString"` + LockTime int `json:"lockTime"` + RefundAgentNodeAddress NodeAddress `json:"refundAgentNodeAddress"` +} + +// Ideally this should be 10 minutes, but realistically... +const AverageBlockTime = 9.465 +const BisqLockTime = 6 * 24 * 10 // 6 blocks an hour * 24 hours a day * 10 days (for alt coin trades) + +func EstimateBlockHeightTime(blockHeight int) time.Time { + loc, _ := time.LoadLocation("America/Vancouver") + return time.Date(2009, 01, 03, 18, 15, 00, 00, loc).Add(time.Minute * time.Duration(int64(math.Round(float64(blockHeight)*AverageBlockTime)))) +} + +func main() { + contractBytes, _ := ioutil.ReadFile(os.Args[1]) + contract := new(BisqContract) + err := json.Unmarshal(contractBytes, contract) + if err == nil { + // Deal with general formatting weirdness. The canonical Bisq hash output is over the contract + // when it has been formatted to separated fields by newlines, and with an indent of 2 spaces + contractOut, _ := json.MarshalIndent(contract, "", " ") + fmt.Printf("Successfully Validated Contract\n") + fmt.Printf("Contract Offer Date: %s\n", time.Unix(int64(contract.OfferPayload.Date/1000), 0)) + fmt.Printf("Contract Block Height %d (estimated) / %s (estimated)\n", contract.LockTime-BisqLockTime, EstimateBlockHeightTime(contract.LockTime-BisqLockTime)) + fmt.Printf("Contract Hash: %x\n", sha256.Sum256(contractOut)) + } else { + fmt.Printf("Error %v", err) + } +}