# Ğchange QRcode RFC
Status: draft
Aim: scan QRcodes in Ğmarkets with Ğecko, to pay securely and easily
Depends on: [unsigned-varint](https://github.com/multiformats/unsigned-varint)
## QRcode content
* magic number (3 bytes)
* Data type (uvarint)
* Price type (uvarint)
* Recipient pubkey (32 bytes)
* Amount
* Data
### Magic number
`0x831614` (this was generated randomly)
This number could be incremented in later versions of the protocol.
### Data type
* 0: None (0 bytes)
* 1: Plain text (until the end)
* 2: Ğchange ad (16 bytes)
Data is placed at the end in order to enable parsing the message even if the client doesn't know the data type.
### Price type
`Value & 0b1111` (the 4 LSB): amount length, in bytes
`Value >> 4` (all the other bits):
* 0: Ğ1, no amount (free price) (then, amount can be empty)
* 1: Ğ1, unit (cent)
* Amount (uvarint)
* 2: Ğ1, UD
* Amount float (uvarint)
* Amount 10 opposite exponent (uvarint)
_example: 12.34 becomes 1234×10^-2; 120 becomes 120×10^0_
Amount length is specified to enable parsing the message even if the client doesn't know the price type.
### Amount
Amount value is encoded in cents, in the current base.
## Python decoding example
```
#!/usr/bin/env python3
from io import BytesIO
import base64, base58, varint
## BytesIO adds a stream interface to bytes
## Example:
qr = BytesIO(bytes.fromhex("8316140212c28e52e034ecaf684fa3e5d755db519074f27ad086bddffd26b386e55f3b623ca01f0177c0f8ce5f6a69764c7bc10263ec"))
## Read from a file:
# qr = open("qrcode-AXfA-M5faml2THvBAmPs.bin", "rb")
## Check magic number
assert qr.read(3) == b"\x83\x16\x14"
## Read data type
data_type = varint.decode_stream(qr)
## Read price type
raw_price_type = varint.decode_stream(qr)
price_type = raw_price_type >> 4
amount_len = raw_price_type & 0b1111
## Read pubkey
pubkey = qr.read(32)
pubkey_b58 = base58.b58encode(pubkey)
print("Pubkey: {}".format(pubkey_b58))
## Read amount
if price_type == 0: # Free price, ignore amount
qr.read(amount_len)
print("Free price")
elif price_type == 1: # Units
amount = varint.decode_stream(qr)
print("Price: {} Ğ1".format(amount/100))
elif price_type == 2: # UD
amount_n = varint.decode_stream(qr)
amount_e = varint.decode_stream(qr)
amount = amount_n * 10 ** -amount_e
print("Price: {} UD_Ğ1".format(amount))
else:
qr.read(amount_len)
print("Error: unknown price type, ignoring price")
## Read data
if data_type == 0: # No data
data = None
print("There is no data")
elif data_type == 1: # Plain text
data = qr.read()
print("Data:")
print(data)
elif data_type == 2: # Ğchange ad
data = base64.urlsafe_b64encode(qr.read(16))
print("Ğchange ad ID: {}".format(data))
```