Skip to content

Commit 14466f9

Browse files
committed
Leeloo Dallas Multipay - Sentinel mutli-send transactor. Batch coin sending.
1 parent e7dbdbb commit 14466f9

File tree

9 files changed

+329
-0
lines changed

9 files changed

+329
-0
lines changed

.DS_Store

6 KB
Binary file not shown.

.github/workflows/tg-notify.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name: tg-notify
2+
on: [push, pull_request]
3+
jobs:
4+
build:
5+
runs-on: ubuntu-latest
6+
steps:
7+
- name: Update status
8+
uses: appleboy/telegram-action@master
9+
with:
10+
to: ${{ secrets.TELEGRAM_TO }}
11+
token: ${{ secrets.TELEGRAM_TOKEN }}
12+
message: | #https://help.github.com/en/actions/reference/contexts-and-expression-syntax-for-github-actions#github-context
13+
${{ github.actor }} created commit:
14+
Commit message: ${{ github.event.head_commit.message }}
15+
16+
Repository: ${{ github.repository }}
17+
18+
Branch: ${{ github.ref_name }}
19+
20+
See changes: https://github.com/${{ github.repository }}/commit/${{github.sha}}

README.md

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,99 @@
11
# MultiPay
2+
23
A Sentinel DVPN Multipay Transactor
4+
5+
This will run in a loop and prompt you for sentinel wallet addresses and amounts that you would like to send in single transaction (batch sending) based on the seed phrase you specify in the scrtxxs file.
6+
7+
# Installation
8+
9+
* requires sentinel-sdk
10+
11+
* requires >= python 3.10
12+
13+
To install the dependency:
14+
15+
```shell
16+
pip install sentinel-sdk
17+
```
18+
19+
Clone the repository
20+
21+
```shell
22+
git clone https://github.com/MathNodes/MultiPay
23+
```
24+
25+
# Configuration
26+
27+
Within the repository directory, edit the **scrtxxs.py** to your specific parameters.
28+
29+
* WalletName - The name you will give your sending wallet in the krygin
30+
31+
* HotWalletPW - The Password for your wallet in the keyring
32+
33+
* WalletSeed - The seed phrase of the sending wallet if not already in the keyring. leave blank if you already imported this wallet once before
34+
35+
# Run
36+
37+
To run the MultiPay script do the following:
38+
39+
```shell
40+
python3 SentinelMultiPay.py
41+
```
42+
43+
and follow the on screen prompts
44+
45+
# Logs & Keyring
46+
47+
The log file will be in the following folders
48+
49+
OS X:
50+
51+
```shell
52+
/Users/username/.meile-multi-pay/multipay.log
53+
```
54+
55+
Linux:
56+
57+
```shell
58+
/home/username/.meile-multi-pay/multipay.log
59+
```
60+
61+
This is also the folder the encrypted keyring will reside in.
62+
63+
# Donations
64+
65+
Because we are working on a small grant with no VC funding, any additional contributions to our developer team is more than certainly welcomed. It will help fund future releases.
66+
67+
## BTC (Bitcoin)
68+
69+
```
70+
bc1qtvc9l3cr9u4qg6uwe6pvv7jufvsnn0xxpdyftl
71+
```
72+
73+
![BTC](./img/BTC.png)
74+
75+
## DVPN (Sentinel)
76+
77+
```
78+
sent12v8ghhg98e2n0chyje3su4uqlsg75sh4lwcyww
79+
```
80+
81+
![dvpn](./img/DVPN.png)
82+
83+
## XMR (Monero)
84+
85+
```
86+
87qHJPU5dZGWaWzuoC3My5SgoQSuxh4sHSv1FXRZrQ9XZHWnfC33EX1NLv5HujpVhbPbbF9RcXXD94byT18HonAQ75b9dyR
87+
```
88+
89+
![xmr](./img/XMR.png)
90+
91+
## ARRR (Pirate Chain)
92+
93+
```
94+
zs1gn457262c52z5xa666k77zafqmke0hd60qvc38dk48w9fx378h4zjs5rrwnl0x8qazj4q3x4svz
95+
```
96+
97+
98+
99+
![ARRR](./img/ARRR.png)

SentinelMultiPay.py

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
#!/bin/env python3
2+
3+
import scrtxxs
4+
import requests
5+
import sys
6+
from os import path, mkdir
7+
from urllib.parse import urlparse
8+
from bip_utils import Bip39SeedGenerator, Bip44, Bip44Coins
9+
10+
from sentinel_sdk.sdk import SDKInstance
11+
from sentinel_sdk.types import TxParams
12+
from keyrings.cryptfile.cryptfile import CryptFileKeyring
13+
from sentinel_protobuf.cosmos.base.v1beta1.coin_pb2 import Coin
14+
import ecdsa
15+
import hashlib
16+
import bech32
17+
from mospy import Transaction
18+
from grpc import RpcError
19+
20+
from datetime import datetime
21+
22+
MNAPI = "https://api.sentinel.mathnodes.com"
23+
NODEAPI = "/sentinel/nodes/%s"
24+
GRPC = scrtxxs.GRPC
25+
SSL = True
26+
VERSION = 20240817.0234
27+
SATOSHI = 1000000
28+
29+
class MultiPay():
30+
def __init__(self, keyring_passphrase, wallet_name, seed_phrase = None):
31+
self.wallet_name = wallet_name
32+
33+
if seed_phrase:
34+
seed_bytes = Bip39SeedGenerator(seed_phrase).Generate()
35+
bip44_def_ctx = Bip44.FromSeed(seed_bytes, Bip44Coins.COSMOS).DeriveDefaultPath()
36+
privkey_obj = ecdsa.SigningKey.from_string(bip44_def_ctx.PrivateKey().Raw().ToBytes(), curve=ecdsa.SECP256k1)
37+
pubkey = privkey_obj.get_verifying_key()
38+
s = hashlib.new("sha256", pubkey.to_string("compressed")).digest()
39+
r = hashlib.new("ripemd160", s).digest()
40+
five_bit_r = bech32.convertbits(r, 8, 5)
41+
account_address = bech32.bech32_encode("sent", five_bit_r)
42+
print(account_address)
43+
self.keyring = self.__keyring(keyring_passphrase)
44+
self.keyring.set_password("meile-multi-pay", wallet_name, bip44_def_ctx.PrivateKey().Raw().ToBytes().hex())
45+
else:
46+
self.keyring = self.__keyring(keyring_passphrase)
47+
48+
private_key = self.keyring.get_password("meile-multi-pay", self.wallet_name)
49+
50+
grpcaddr, grpcport = urlparse(GRPC).netloc.split(":")
51+
52+
self.sdk = SDKInstance(grpcaddr, int(grpcport), secret=private_key, ssl=SSL)
53+
54+
self.logfile = open(path.join(scrtxxs.KeyringDIR, "multipay.log"), "a+")
55+
56+
now = datetime.now()
57+
self.logfile.write(f"\n---------------------------{now}---------------------------\n")
58+
59+
def __keyring(self, keyring_passphrase: str):
60+
if not path.isdir(scrtxxs.KeyringDIR):
61+
mkdir(scrtxxs.KeyringDIR)
62+
63+
kr = CryptFileKeyring()
64+
kr.filename = "keyring.cfg"
65+
kr.file_path = path.join(scrtxxs.KeyringDIR, kr.filename)
66+
kr.keyring_key = keyring_passphrase
67+
return kr
68+
69+
def __get_balance(self, address):
70+
CoinDict = {'dvpn' : 0, 'scrt' : 0, 'dec' : 0, 'atom' : 0, 'osmo' : 0}
71+
#CoinDict = {'tsent' : 0, 'scrt' : 0, 'dec' : 0, 'atom' : 0, 'osmo' : 0}
72+
endpoint = "/bank/balances/" + address
73+
try:
74+
r = requests.get(MNAPI + endpoint)
75+
coinJSON = r.json()
76+
except:
77+
return None
78+
79+
print(coinJSON)
80+
try:
81+
for coin in coinJSON['result']:
82+
if "udvpn" in coin['denom']:
83+
CoinDict['dvpn'] = int(coin['amount'])
84+
except Exception as e:
85+
print(str(e))
86+
return None
87+
return CoinDict
88+
89+
def SendDVPNs(self, addr_amts):
90+
balance = self.__get_balance(self.sdk._account.address)
91+
wallet_balance = int(balance.get("dvpn", 0))
92+
93+
amt = 0
94+
95+
# Sum total amount
96+
for amount in addr_amts.values():
97+
amt += int(amount)
98+
99+
if wallet_balance < int(amt):
100+
self.logfile.write(f"[sp]: Balance is too low, required: {amt}udvpn, found: {wallet_balance}udvpn\n")
101+
return False
102+
103+
tx_params = TxParams(
104+
gas=300000,
105+
gas_multiplier=1.15,
106+
fee_amount=30000,
107+
denom="udvpn"
108+
)
109+
110+
tx = Transaction(
111+
account=self.sdk._account,
112+
fee=Coin(denom=tx_params.denom, amount=f"{tx_params.fee_amount}"),
113+
gas=tx_params.gas,
114+
protobuf="sentinel",
115+
chain_id="sentinelhub-2",
116+
)
117+
118+
119+
for addr,udvpn in addr_amts.items():
120+
tx.add_msg(
121+
tx_type='transfer',
122+
sender=self.sdk._account,
123+
receipient=addr,
124+
amount=udvpn,
125+
denom="udvpn",
126+
)
127+
128+
self.sdk._client.load_account_data(account=self.sdk._account)
129+
130+
if tx_params.gas == 0:
131+
self.sdk._client.estimate_gas(
132+
transaction=tx, update=True, multiplier=tx_params.gas_multiplier
133+
)
134+
135+
tx_height = 0
136+
try:
137+
tx = self.sdk._client.broadcast_transaction(transaction=tx)
138+
139+
except RpcError as rpc_error:
140+
details = rpc_error.details()
141+
print("details", details)
142+
print("code", rpc_error.code())
143+
print("debug_error_string", rpc_error.debug_error_string())
144+
self.logfile.write("[sp]: RPC ERROR. ")
145+
return False
146+
147+
if tx.get("log", None) is None:
148+
tx_response = self.sdk.nodes.wait_for_tx(tx["hash"])
149+
tx_height = tx_response.get("txResponse", {}).get("height", 0) if isinstance(tx_response, dict) else tx_response.tx_response.height
150+
151+
message = f"Succefully sent {amt}udvpn at height: {tx_height} distributed by {addr_amts}" if tx.get("log", None) is None else tx["log"]
152+
self.logfile.write(f"[sp]: {message}\n")
153+
return True
154+
155+
156+
if __name__ == "__main__":
157+
mp = MultiPay(scrtxxs.HotWalletPW, scrtxxs.WalletName, scrtxxs.WalletSeed)
158+
159+
SendDict = {}
160+
161+
print(f"Leeloo Dallas Multipay - A DVPN multipay transactor - by freQniK - version: 5th Element {VERSION}\n\n")
162+
print("You will be presented with a loop to enter Sentinel wallet addresses and amt. When finished, enter 'done'")
163+
while True:
164+
addr = input("Enter wallet address: ")
165+
if addr.upper() == "DONE":
166+
break
167+
amt = input("Enter dvpn amt to send to wallet: ")
168+
169+
SendDict[addr] = str(int(float(amt) / SATOSHI))
170+
171+
print("The following addresses will receive these repsective amounts: ")
172+
print(SendDict)
173+
answer = input("Would you iike to continue (Y/n): ")
174+
if answer.upper() == "Y":
175+
if mp.SendDVPNs(SendDict):
176+
print("Transaction completed successfully. Please check the log file")
177+
print(f"{scrtxxs.KeyringDIR}/multipay.log")
178+
else:
179+
print("Something went wrong. Please check the log file.")
180+
print(f"{scrtxxs.KeyringDIR}/multipay.log")
181+
else:
182+
sys.exit(0)
183+
184+

img/ARRR.png

58.7 KB
Loading

img/BTC.png

15.9 KB
Loading

img/DVPN.png

12.5 KB
Loading

img/XMR.png

59.2 KB
Loading

scrtxxs.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
'''
2+
You need to edit the following variables below with your desired values:
3+
4+
WalletName - Whatever you want to name the wallet in the keyring
5+
HotWalletPW - Passowrd for your wallet in the keyring
6+
WalletSeed - Seed if it is a new wallet, o/w it will pull from the keyring the WalletName
7+
8+
'''
9+
10+
11+
import pwd
12+
import os
13+
14+
import platform
15+
16+
pltform = platform.system()
17+
18+
if pltform == "Darwin":
19+
KeyringDIR = "/Users/" + str(pwd.getpwuid(os.getuid())[0]) + "/.meile-multi-pay"
20+
else:
21+
KeyringDIR = "/home/" + str(pwd.getpwuid(os.getuid())[0]) + "/.meile-multi-pay"
22+
23+
WalletName = ""
24+
HotWalletPW = ""
25+
WalletSeed = ""
26+
GRPC = "https://grpc.bluefren.xyz:443"
27+
28+

0 commit comments

Comments
 (0)