-
Notifications
You must be signed in to change notification settings - Fork 13
/
echopay.py
130 lines (100 loc) · 5.13 KB
/
echopay.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#!/usr/bin/python3.9
import asyncio
from decimal import Decimal
from typing import Union
import mc_util
from forest.core import Message, PayBot, Response, requires_admin, run_bot
FEE_PMOB = int(1e12 * 0.0004) # Mobilecoin transaction fee in Picomob.
class Echopay(PayBot):
"""A simple Payments Enabled Bot"""
def __init__(self) -> None:
"""Creates AND STARTS a bot that routes commands to do_x handlers"""
super().__init__()
asyncio.create_task(self.set_payment_address())
@staticmethod
def to_mob(amount_picomob: int) -> Decimal:
"""converts amount from pmob to mob"""
return mc_util.pmob2mob(amount_picomob).quantize(Decimal("1.0000"))
@staticmethod
def to_picomob(amount_mob: Union[int, float, Decimal]) -> int:
"""converts amount from mob to picomob"""
return mc_util.mob2pmob(amount_mob)
async def set_payment_address(self) -> None:
"""Updates the Bot Signal Profile to have the correct payments address
as specified by FS_ACCOUNT_NAME"""
fs_address = await self.mobster.get_my_address()
# Singal addresses require Base64 encoding, but full service uses Base58.
# This method handles the conversion
signal_address = mc_util.b58_wrapper_to_b64_public_address(fs_address)
# This will set the bot's Signal profile, replace avatar.png to give your bot a custom avatar
await self.set_profile_auxin(
given_name="Echopay",
family_name="",
payment_address=signal_address,
# profile_path="avatar.png",
)
async def do_payme(self, message: Message) -> Response:
"""Sends payment to requestee for a certain amount"""
amount_mob = 0.001 ##payment amount in MOB
amount_picomob = self.to_picomob(amount_mob)
password = "please"
# for convenience, message.arg0 is the first word of the message in this case "payme"
# and msg.arg1 is the next word after that. In "payme please" please is msg.arg1
if message.arg1 == password:
payment_status = await self.send_payment(
message.source,
amount_picomob,
confirm_tx_timeout=10,
receipt_message="",
)
# This check verifies that the payment succeeded.
if getattr(payment_status, "status", "") == "tx_status_succeeded":
return f"Sent you a payment for {str(amount_mob)} MOB"
return "There was a problem processing your payment, please ask an admininstrator for help"
if message.arg1 is None:
return "What's the secret word?"
return "That's not the right secret word!!"
@requires_admin
async def do_pay_user(self, message: Message) -> Response:
"""Send payment to user by phone number: `pay_user +15554135555`"""
amount_mob = 0.001
amount_picomob = self.to_picomob(amount_mob)
# for convenience, message.arg0 is the first word of the message in this case "pay_user"
# and msg.arg1 is the next word after that. message.arg1 should be a phone number
# send_payment takes care of validating that it is a proper recipient,
# but for type safety we first check that it exists and is a string
if not isinstance(message.arg1, str):
response = (
"Please specify the User to be paid as a phone number"
" with country code example: pay_user +15554135555"
)
return response
recipient = message.arg1
payment_status = await self.send_payment(
recipient,
amount_picomob,
confirm_tx_timeout=10,
receipt_message="Here's some money from your friendly Paymebot",
)
# This check verifies that the payment succeeded.
if getattr(payment_status, "status", "") == "tx_status_succeeded":
return f"Sent Payment to {recipient} for {amount_mob} MOB"
return "There was a problem processing your payment, please ask an admininstrator for help"
async def payment_response(self, msg: Message, amount_pmob: int) -> Response:
"""Triggers on Succesful payment, overriden from forest.core"""
# amounts are received in picoMob, convert to Mob for readability
amount_mob = self.to_mob(amount_pmob)
amount_to_return = amount_pmob - FEE_PMOB
if amount_to_return < 0:
return f"Thank you for your payment of {str(amount_mob)} MOB. This payment is for less than the Network Fee (0.0004 MOB), so I can't return it to you."
payment_status = await self.send_payment(
msg.source,
amount_to_return,
confirm_tx_timeout=10,
receipt_message="",
)
if getattr(payment_status, "status", "") == "tx_status_succeeded":
return f"Thank you for your payment of {str(amount_mob)} MOB. Here's your money back, minus the network fee, {str(self.to_mob(amount_to_return))} MOB."
return "Couldn't return your payment for some reason. Please contact administrator for assistance."
if __name__ == "__main__":
run_bot(Echopay)