コード例 #1
0
    def create(self,
               expiration_date,
               metadata_category,
               title,
               description,
               currency_code,
               price,
               process_time,
               nsfw,
               shipping_origin=None,
               shipping_regions=None,
               est_delivery_domestic=None,
               est_delivery_international=None,
               terms_conditions=None,
               returns=None,
               keywords=None,
               category=None,
               condition=None,
               sku=None,
               images=None,
               free_shipping=None,
               shipping_currency_code=None,
               shipping_domestic=None,
               shipping_international=None,
               options=None,
               moderators=None):
        """
        All parameters are strings except:

        :param expiration_date: `string` (must be formatted UTC datetime)
        :param keywords: `list`
        :param nsfw: `boolean`
        :param images: a `list` of image files
        :param free_shipping: `boolean`
        :param shipping_origin: a 'string' formatted `CountryCode`
        :param shipping_regions: a 'list' of 'string' formatted `CountryCode`s
        :param options: a 'dict' containing options as keys and 'list' as option values.
        :param moderators: a 'list' of 'string' guids (hex encoded).
        """

        profile = Profile(self.db).get()
        self.contract = OrderedDict({
            "vendor_offer": {
                "listing": {
                    "metadata": {
                        "version": "0.1",
                        "category": metadata_category.lower(),
                        "category_sub": "fixed price"
                    },
                    "id": {
                        "guid": self.keychain.guid.encode("hex"),
                        "pubkeys": {
                            "guid":
                            self.keychain.guid_signed_pubkey[64:].encode(
                                "hex"),
                            "bitcoin":
                            bitcoin.bip32_extract_key(
                                self.keychain.bitcoin_master_pubkey),
                            "encryption":
                            self.keychain.encryption_pubkey.encode("hex")
                        }
                    },
                    "item": {
                        "title": title,
                        "description": description,
                        "process_time": process_time,
                        "price_per_unit": {},
                        "nsfw": nsfw
                    }
                }
            }
        })
        if expiration_date == "":
            self.contract["vendor_offer"]["listing"]["metadata"][
                "expiry"] = "never"
        else:
            self.contract["vendor_offer"]["listing"]["metadata"][
                "expiry"] = expiration_date + " UTC"
        if metadata_category == "physical good" and condition is not None:
            self.contract["vendor_offer"]["listing"]["item"][
                "condition"] = condition
        if currency_code.upper() == "BTC":
            item = self.contract["vendor_offer"]["listing"]["item"]
            item["price_per_unit"]["bitcoin"] = price
        else:
            item = self.contract["vendor_offer"]["listing"]["item"]
            item["price_per_unit"]["fiat"] = {}
            item["price_per_unit"]["fiat"]["price"] = price
            item["price_per_unit"]["fiat"]["currency_code"] = currency_code
        if keywords is not None:
            self.contract["vendor_offer"]["listing"]["item"]["keywords"] = []
            self.contract["vendor_offer"]["listing"]["item"][
                "keywords"].extend(keywords)
        if category is not None:
            self.contract["vendor_offer"]["listing"]["item"][
                "category"] = category
        if sku is not None:
            self.contract["vendor_offer"]["listing"]["item"]["sku"] = sku
        if options is not None:
            self.contract["vendor_offer"]["listing"]["item"][
                "options"] = options
        if metadata_category == "physical good":
            self.contract["vendor_offer"]["listing"]["shipping"] = {}
            shipping = self.contract["vendor_offer"]["listing"]["shipping"]
            shipping["shipping_origin"] = shipping_origin
            if free_shipping is False:
                self.contract["vendor_offer"]["listing"]["shipping"][
                    "free"] = False
                self.contract["vendor_offer"]["listing"]["shipping"][
                    "flat_fee"] = {}
                if shipping_currency_code == "BTC":
                    self.contract["vendor_offer"]["listing"]["shipping"][
                        "flat_fee"]["bitcoin"] = {}
                    self.contract["vendor_offer"]["listing"]["shipping"][
                        "flat_fee"]["bitcoin"]["domestic"] = shipping_domestic
                    self.contract["vendor_offer"]["listing"]["shipping"][
                        "flat_fee"]["bitcoin"][
                            "international"] = shipping_international
                else:
                    shipping = self.contract["vendor_offer"]["listing"][
                        "shipping"]
                    shipping["flat_fee"]["fiat"] = {}
                    shipping["flat_fee"]["fiat"]["price"] = {}
                    shipping["flat_fee"]["fiat"]["price"][
                        "domestic"] = shipping_domestic
                    shipping["flat_fee"]["fiat"]["price"][
                        "international"] = shipping_international
                    shipping["flat_fee"]["fiat"][
                        "currency_code"] = shipping_currency_code
            else:
                self.contract["vendor_offer"]["listing"]["shipping"][
                    "free"] = True
            self.contract["vendor_offer"]["listing"]["shipping"][
                "shipping_regions"] = []
            for region in shipping_regions:
                shipping = self.contract["vendor_offer"]["listing"]["shipping"]
                shipping["shipping_regions"].append(region)
            listing = self.contract["vendor_offer"]["listing"]
            listing["shipping"]["est_delivery"] = {}
            listing["shipping"]["est_delivery"][
                "domestic"] = est_delivery_domestic
            listing["shipping"]["est_delivery"][
                "international"] = est_delivery_international
        if profile.HasField("handle"):
            self.contract["vendor_offer"]["listing"]["id"][
                "blockchain_id"] = profile.handle
        if images is not None:
            self.contract["vendor_offer"]["listing"]["item"][
                "image_hashes"] = []
            for image_hash in images:
                if len(image_hash) != 40:
                    raise Exception("Invalid image hash")
                self.contract["vendor_offer"]["listing"]["item"][
                    "image_hashes"].append(image_hash)
        if terms_conditions is not None or returns is not None:
            self.contract["vendor_offer"]["listing"]["policy"] = {}
            if terms_conditions is not None:
                self.contract["vendor_offer"]["listing"]["policy"][
                    "terms_conditions"] = terms_conditions
            if returns is not None:
                self.contract["vendor_offer"]["listing"]["policy"][
                    "returns"] = returns
        if moderators is not None:
            self.contract["vendor_offer"]["listing"]["moderators"] = []
            for mod in moderators:
                mod_info = self.db.ModeratorStore().get_moderator(
                    unhexlify(mod))
                print mod_info
                if mod_info is not None:
                    moderator = {
                        "guid": mod,
                        "blockchain_id": mod_info[6],
                        "pubkeys": {
                            "signing": {
                                "key": mod_info[1][64:].encode("hex"),
                                "signature": mod_info[1][:64].encode("hex")
                            },
                            "encryption": {
                                "key": mod_info[2].encode("hex"),
                                "signature": mod_info[3].encode("hex")
                            },
                            "bitcoin": {
                                "key": mod_info[4].encode("hex"),
                                "signature": mod_info[5].encode("hex")
                            }
                        }
                    }
                    self.contract["vendor_offer"]["listing"][
                        "moderators"].append(moderator)

        listing = json.dumps(self.contract["vendor_offer"]["listing"],
                             indent=4)
        self.contract["vendor_offer"]["signature"] = \
            self.keychain.signing_key.sign(listing, encoder=nacl.encoding.HexEncoder)[:128]
        self.save()
コード例 #2
0
    def create(self,
               expiration_date,
               metadata_category,
               title,
               description,
               currency_code,
               price,
               process_time,
               nsfw,
               shipping_origin,
               shipping_regions,
               est_delivery_domestic=None,
               est_delivery_international=None,
               keywords=None,
               category=None,
               condition=None,
               sku=None,
               images=None,
               free_shipping=None,
               shipping_currency_code=None,
               shipping_domestic=None,
               shipping_international=None):
        """
        All parameters are strings except:

        :param expiration_date: `string` (must be formatted UTC datetime)
        :param keywords: `list`
        :param nsfw: `boolean`
        :param images: a `list` of image files
        :param free_shipping: `boolean`
        :param shipping_origin: a 'string' formatted `CountryCode`
        :param shipping_regions: a 'list' of 'string' formatted `CountryCode`s
        """

        # TODO: import keys into the contract, import moderator information from db, sign contract.
        profile = Profile().get()
        keychain = KeyChain()
        self.contract = OrderedDict({
            "vendor_offer": {
                "listing": {
                    "metadata": {
                        "version": "0.1",
                        "expiry": expiration_date + " UTC",
                        "category": metadata_category,
                        "category_sub": "fixed price"
                    },
                    "id": {
                        "guid": keychain.guid.encode("hex"),
                        "pubkeys": {
                            "guid":
                            keychain.guid_signed_pubkey[64:].encode("hex"),
                            "bitcoin": keychain.bitcoin_master_pubkey
                        }
                    },
                    "item": {
                        "title": title,
                        "description": description,
                        "process_time": process_time,
                        "price_per_unit": {},
                        "nsfw": nsfw
                    }
                }
            }
        })
        if metadata_category == "physical good" and condition is not None:
            self.contract["vendor_offer"]["listing"]["item"][
                "condition"] = condition
        if currency_code.upper() == "BTC":
            item = self.contract["vendor_offer"]["listing"]["item"]
            item["price_per_unit"]["bitcoin"] = price
        else:
            item = self.contract["vendor_offer"]["listing"]["item"]
            item["price_per_unit"]["fiat"] = {}
            item["price_per_unit"]["fiat"]["price"] = price
            item["price_per_unit"]["fiat"]["currency_code"] = currency_code
        if keywords is not None:
            self.contract["vendor_offer"]["listing"]["item"]["keywords"] = []
            self.contract["vendor_offer"]["listing"]["item"][
                "keywords"].extend(keywords)
        if category is not None:
            self.contract["vendor_offer"]["listing"]["item"][
                "category"] = category
        if sku is not None:
            self.contract["vendor_offer"]["listing"]["item"]["sku"] = sku
        if metadata_category == "physical good":
            self.contract["vendor_offer"]["listing"]["shipping"] = {}
            shipping = self.contract["vendor_offer"]["listing"]["shipping"]
            shipping["shipping_origin"] = shipping_origin
            if free_shipping is False:
                self.contract["vendor_offer"]["listing"]["shipping"][
                    "free"] = False
                self.contract["vendor_offer"]["listing"]["shipping"][
                    "flat_fee"] = {}
                if shipping_currency_code == "BTC":
                    self.contract["vendor_offer"]["listing"]["shipping"][
                        "flat_fee"]["bitcoin"] = {}
                    self.contract["vendor_offer"]["listing"]["shipping"][
                        "flat_fee"]["bitcoin"]["domestic"] = shipping_domestic
                    self.contract["vendor_offer"]["listing"]["shipping"][
                        "flat_fee"]["bitcoin"][
                            "international"] = shipping_international
                else:
                    shipping = self.contract["vendor_offer"]["listing"][
                        "shipping"]
                    shipping["flat_fee"]["fiat"] = {}
                    shipping["flat_fee"]["fiat"]["price"] = {}
                    shipping["flat_fee"]["fiat"]["price"][
                        "domestic"] = shipping_domestic
                    shipping["flat_fee"]["fiat"]["price"][
                        "international"] = shipping_international
                    shipping["flat_fee"]["fiat"][
                        "currency_code"] = shipping_currency_code
            else:
                self.contract["vendor_offer"]["listing"]["shipping"][
                    "free"] = True
            self.contract["vendor_offer"]["listing"]["shipping"][
                "shipping_regions"] = []
            for region in shipping_regions:
                shipping = self.contract["vendor_offer"]["listing"]["shipping"]
                shipping["shipping_regions"].append(region)
            listing = self.contract["vendor_offer"]["listing"]
            listing["shipping"]["est_delivery"] = {}
            listing["shipping"]["est_delivery"][
                "domestic"] = est_delivery_domestic
            listing["shipping"]["est_delivery"][
                "international"] = est_delivery_international
        if profile.HasField("handle"):
            self.contract["vendor_offer"]["listing"]["id"][
                "blockchain_id"] = profile.handle
        if images is not None:
            self.contract["vendor_offer"]["listing"]["item"][
                "image_hashes"] = []
            for image in images:
                hash_value = digest(image).encode("hex")
                self.contract["vendor_offer"]["listing"]["item"][
                    "image_hashes"].append(hash_value)
                with open(DATA_FOLDER + "store/media/" + hash_value,
                          'w') as outfile:
                    outfile.write(image)
                HashMap().insert(digest(image),
                                 DATA_FOLDER + "store/media/" + hash_value)

        listing = json.dumps(self.contract["vendor_offer"]["listing"],
                             indent=4)
        self.contract["vendor_offer"]["signature"] = \
            keychain.signing_key.sign(listing, encoder=nacl.encoding.HexEncoder)[:128]
        self.save()
コード例 #3
0
    def add_purchase_info(self,
                          quantity,
                          ship_to=None,
                          shipping_address=None,
                          city=None,
                          state=None,
                          postal_code=None,
                          country=None,
                          moderator=None,
                          options=None):
        """
        Update the contract with the buyer's purchase information.
        """

        profile = Profile(self.db).get()
        order_json = {
            "buyer_order": {
                "order": {
                    "ref_hash":
                    digest(json.dumps(self.contract, indent=4)).encode("hex"),
                    "quantity":
                    quantity,
                    "id": {
                        "guid": self.keychain.guid.encode("hex"),
                        "pubkeys": {
                            "guid":
                            self.keychain.guid_signed_pubkey[64:].encode(
                                "hex"),
                            "bitcoin":
                            bitcoin.bip32_extract_key(
                                self.keychain.bitcoin_master_pubkey),
                            "encryption":
                            self.keychain.encryption_pubkey.encode("hex")
                        }
                    },
                    "payment": {}
                }
            }
        }
        if profile.HasField("handle"):
            order_json["buyer_order"]["order"]["id"][
                "blockchain_id"] = profile.handle
        if self.contract["vendor_offer"]["listing"]["metadata"][
                "category"] == "physical good":
            order_json["buyer_order"]["order"]["shipping"] = {}
            order_json["buyer_order"]["order"]["shipping"]["ship_to"] = ship_to
            order_json["buyer_order"]["order"]["shipping"][
                "address"] = shipping_address
            order_json["buyer_order"]["order"]["shipping"]["city"] = city
            order_json["buyer_order"]["order"]["shipping"]["state"] = state
            order_json["buyer_order"]["order"]["shipping"][
                "postal_code"] = postal_code
            order_json["buyer_order"]["order"]["shipping"]["country"] = country
        if options is not None:
            order_json["buyer_order"]["order"]["options"] = options
        if moderator:  # TODO: Handle direct payments
            chaincode = sha256(str(
                random.getrandbits(256))).digest().encode("hex")
            order_json["buyer_order"]["order"]["payment"][
                "chaincode"] = chaincode
            valid_mod = False
            for mod in self.contract["vendor_offer"]["listing"]["moderators"]:
                if mod["guid"] == moderator:
                    order_json["buyer_order"]["order"]["moderator"] = moderator
                    masterkey_m = mod["pubkeys"]["bitcoin"]["key"]
                    valid_mod = True
            if not valid_mod:
                return False
            masterkey_b = bitcoin.bip32_extract_key(
                self.keychain.bitcoin_master_pubkey)
            masterkey_v = self.contract["vendor_offer"]["listing"]["id"][
                "pubkeys"]["bitcoin"]
            buyer_key = derive_childkey(masterkey_b, chaincode)
            vendor_key = derive_childkey(masterkey_v, chaincode)
            moderator_key = derive_childkey(masterkey_m, chaincode)

            redeem_script = bitcoin.mk_multisig_script(
                [buyer_key, vendor_key, moderator_key], 2)
            order_json["buyer_order"]["order"]["payment"][
                "redeem_script"] = redeem_script
            if self.testnet:
                payment_address = bitcoin.p2sh_scriptaddr(redeem_script, 196)
            else:
                payment_address = bitcoin.p2sh_scriptaddr(redeem_script)
            order_json["buyer_order"]["order"]["payment"][
                "address"] = payment_address

        price_json = self.contract["vendor_offer"]["listing"]["item"][
            "price_per_unit"]
        if "bitcoin" in price_json:
            order_json["buyer_order"]["order"]["payment"][
                "amount"] = price_json["bitcoin"]
        else:
            currency_code = price_json["fiat"]["currency_code"]
            fiat_price = price_json["fiat"]["price"]
            try:
                request = Request('https://api.bitcoinaverage.com/ticker/' +
                                  currency_code.upper() + '/last')
                response = urlopen(request)
                conversion_rate = response.read()
            except URLError:
                return False
            order_json["buyer_order"]["order"]["payment"]["amount"] = float(
                "{0:.8f}".format(float(fiat_price) / float(conversion_rate)))

        self.contract["buyer_order"] = order_json["buyer_order"]
        order = json.dumps(self.contract["buyer_order"]["order"], indent=4)
        # TODO: This should also be signed with the bitcoin key. It's the only way a moderator
        # will have to link this contract to a bitcoin transaction.
        self.contract["buyer_order"]["signature"] = \
            self.keychain.signing_key.sign(order, encoder=nacl.encoding.HexEncoder)[:128]
        return (self.contract["buyer_order"]["order"]["payment"]["address"],
                order_json["buyer_order"]["order"]["payment"]["amount"])