func (n *OpenBazaarNode) Purchase(data *PurchaseData) error { // TODO: validate the purchase data is formatted properly contract := new(pb.RicardianContract) order := new(pb.Order) order.RefundAddress = n.Wallet.GetCurrentAddress(bitcoin.REFUND).EncodeAddress() order.Shipping.ShipTo = data.shipTo order.Shipping.Address = data.address order.Shipping.City = data.city order.Shipping.State = data.state order.Shipping.PostalCode = data.postalCode order.Shipping.Country = pb.CountryCode(pb.CountryCode_value[data.countryCode]) // TODO: Add blockchain ID to order order.BuyerID.Guid = n.IpfsNode.Identity.Pretty() pubkey, err := n.IpfsNode.PrivateKey.GetPublic().Bytes() if err != nil { return err } order.BuyerID.Pubkeys.Guid = pubkey order.BuyerID.Pubkeys.Bitcoin = n.Wallet.GetMasterPublicKey().Key order.Timestamp = uint64(time.Now().Unix()) for _, item := range data.items { i := new(pb.Order_Item) b, err := ipfs.Cat(n.Context, item.listingHash) if err != nil { return err } rc := new(pb.RicardianContract) err = jsonpb.UnmarshalString(string(b), rc) if err != nil { return err } // TODO: validate signatures on this contract before we purchase it contract.VendorListings = append(contract.VendorListings, rc.VendorListings[0]) contract.Signatures = append(contract.Signatures, rc.Signatures[0]) ser, err := proto.Marshal(rc.VendorListings[0]) if err != nil { return err } h := sha256.Sum256(ser) i.ListingHash = h[:] i.Quantity = uint32(item.quantity) for _, option := range item.options { o := new(pb.Order_Item_Option) o.Name = option.name o.Value = option.value i.Options = append(i.Options, o) } order.Items = append(order.Items, i) } // TODO: create payment obj // TODO: send to vendor return nil }
// Add our identity to the listings and sign it func (n *OpenBazaarNode) SignListing(listing *pb.Listing) (*pb.RicardianContract, error) { c := new(pb.RicardianContract) if err := validate(listing); err != nil { return c, err } id := new(pb.ID) id.Guid = n.IpfsNode.Identity.Pretty() pubkey, err := n.IpfsNode.PrivateKey.GetPublic().Bytes() if err != nil { return c, err } //TODO: add blockchain ID to listing p := new(pb.ID_Pubkeys) p.Guid = pubkey p.Bitcoin = n.Wallet.GetMasterPublicKey().Key id.Pubkeys = p listing.VendorID = id s := new(pb.Signatures) s.Section = pb.Signatures_LISTING serializedListing, err := proto.Marshal(listing) if err != nil { return c, err } guidSig, err := n.IpfsNode.PrivateKey.Sign(serializedListing) if err != nil { return c, err } priv, _ := ec.PrivKeyFromBytes(ec.S256(), n.Wallet.GetMasterPrivateKey().Key) hashed := sha256.Sum256(serializedListing) bitcoinSig, err := priv.Sign(hashed[:]) if err != nil { return c, err } s.Guid = guidSig s.Bitcoin = bitcoinSig.Serialize() c.VendorListings = append(c.VendorListings, listing) c.Signatures = append(c.Signatures, s) return c, nil }