Skip to content

Commit

Permalink
Id/add paywallet (#47)
Browse files Browse the repository at this point in the history
* add show_details to expand information present in a b58 string

* black

* add /paywallet!

* black up

* bump workflows cache key

* conditional around Optional type

* slightly better typing

* fix mobfriend else-after-return

* fix mobfriend else-after-return

* fix docs typo

Co-authored-by: infra <infra@sterile.solutions>
  • Loading branch information
itdaniher and i-infra authored Dec 14, 2021
1 parent 715f4ba commit 8db5c28
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 13 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
uses: actions/cache@v1
with:
path: ~/.local/share/virtualenvs
key: '${{ runner.os }}-pipenv-${{ hashFiles(''**/Pipfile.lock'') }}'
key: '${{ runner.os }}-pipenv-v2-${{ hashFiles(''**/Pipfile.lock'') }}'
- name: Install dependencies
if: steps.cache-pipenv.outputs.cache-hit != 'true'
run: pipenv install --deploy --dev
Expand Down
18 changes: 12 additions & 6 deletions mc_util/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Copyright (c) 2021 MobileCoin Inc.
# Copyright (c) 2021 The Forest Team
from decimal import Decimal
from typing import Union
from typing import Union, Optional
import zlib
import base64

Expand Down Expand Up @@ -60,22 +60,28 @@ def b64_public_address_to_b58_wrapper(b64_string: str) -> str:
# > new messages without breaking backwards compatibility

# this can be used to import a gift card's entropy into full-service
def b58_wrapper_to_protobuf(b58_string: str) -> printable_pb2.PrintableWrapper:
def b58_wrapper_to_protobuf(
b58_string: str,
) -> Optional[printable_pb2.PrintableWrapper]:
"""Convert a b58-encoded PrintableWrapper into a protobuf
It could be a public address, a gift code, or a payment request"""
checksum_and_wrapper_bytes = base58.b58decode(b58_string)
wrapper_bytes = checksum_and_wrapper_bytes[4:]
if add_checksum_and_b58(wrapper_bytes) != b58_string:
return None
wrapper = printable_pb2.PrintableWrapper()
wrapper.ParseFromString(wrapper_bytes)
return wrapper


def b58_wrapper_to_b64_public_address(b58_string: str) -> str:
def b58_wrapper_to_b64_public_address(b58_string: str) -> Optional[str]:
"""Convert a b58-encoded PrintableWrapper address into a b64-encoded PublicAddress protobuf"""
wrapper = b58_wrapper_to_protobuf(b58_string)
public_address = wrapper.public_address
public_address_bytes = public_address.SerializeToString()
return base64.b64encode(public_address_bytes).decode("utf-8")
if wrapper:
public_address = wrapper.public_address
public_address_bytes = public_address.SerializeToString()
return base64.b64encode(public_address_bytes).decode("utf-8")
return None


def add_checksum_and_b58(wrapper_bytes: bytes) -> str:
Expand Down
63 changes: 57 additions & 6 deletions mobfriend/mobfriend.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,10 +175,20 @@ async def do_check(self, msg: Message) -> Response:
return await self.do_check_balance(msg)
return status.get("result")

@hide
async def do_create_payment_request(self, msg: Message) -> Response:
async def do_show_details(self, msg: Message) -> Response:
"""
/show_details [base58 code]
Returns detailed information about a base58 code."""
if msg.arg1:
details = mc_util.b58_wrapper_to_protobuf(msg.arg1)
if details:
return str(details)
return "Sorry, the provided code has an invalid checksum."
return "Please provide a base58 code!"

async def do_payme(self, msg: Message) -> Response:
"""
/create_payment_request [amount] [memo]
/payme [amount] [memo]
Creates a payment request (as QR code and b58 code to copy and paste.)
For example, /payme 1.0 "Pay me a MOB!"
Expand All @@ -190,8 +200,15 @@ async def do_create_payment_request(self, msg: Message) -> Response:
if not address:
return "Unable to retrieve your MobileCoin address!"
payload = mc_util.printable_pb2.PrintableWrapper()
address_proto = mc_util.b58_wrapper_to_protobuf(address).public_address
payload.payment_request.public_address.CopyFrom(address_proto)
address_proto = mc_util.b58_wrapper_to_protobuf(address)
if address_proto:
payload.payment_request.public_address.CopyFrom(
address_proto.public_address
)
else:
return (
"Sorry, could not parse a valid MobileCoin address from your profile!"
)
if msg.tokens and not (
isinstance(msg.tokens[0], str)
and len(msg.tokens) > 0
Expand All @@ -214,7 +231,41 @@ async def do_create_payment_request(self, msg: Message) -> Response:
)
return payment_request_b58

do_payme = hide(do_create_payment_request)
async def do_paywallet(self, msg: Message) -> Response:
"""
/paywallet [b58address] [amount] [memo]
Creates a payment request (as QR code and b58 code to copy and paste.)
For example, /paywallet [address] 1.0 "Pay me a MOB!"
will create a payment request with
* the destination [b58address],
* a 1MOB value,
* the memo "Pay me a MOB!"
"""
address = msg.arg1
amount = msg.arg2
memo = msg.arg3 or ""
if not address:
return "Please provide your b58 address as the first argument!"
payload = mc_util.printable_pb2.PrintableWrapper()
address_proto = mc_util.b58_wrapper_to_protobuf(address)
if not address_proto:
return "Sorry, could not find a valid address!"
payload.payment_request.public_address.CopyFrom(address_proto.public_address)
if not amount or not amount.replace(".", "0", 1).isnumeric():
return "Sorry, you need to provide a price (in MOB)!"
payload.payment_request.value = mob2pmob(Decimal(amount))
payload.payment_request.memo = memo
payment_request_b58 = mc_util.add_checksum_and_b58(payload.SerializeToString())
pyqrcode.QRCode(payment_request_b58).png(
f"/tmp/{msg.timestamp}.png", scale=5, quiet_zone=10
)
await self.send_message(
recipient=msg.source,
attachments=[f"/tmp/{msg.timestamp}.png"],
msg="Scan me in the Mobile Wallet!",
)
return payment_request_b58

async def do_qr(self, msg: Message) -> Response:
"""
Expand Down

0 comments on commit 8db5c28

Please sign in to comment.