shadowPaySDK 0.2.1__tar.gz → 16.7.2025.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {shadowpaysdk-0.2.1 → shadowpaysdk-16.7.2025.1}/PKG-INFO +20 -7
- shadowpaysdk-16.7.2025.1/README.md +21 -0
- {shadowpaysdk-0.2.1 → shadowpaysdk-16.7.2025.1}/setup.py +6 -6
- {shadowpaysdk-0.2.1 → shadowpaysdk-16.7.2025.1}/shadowPaySDK/__init__.py +1 -3
- {shadowpaysdk-0.2.1 → shadowpaysdk-16.7.2025.1}/shadowPaySDK/const.py +15 -3
- {shadowpaysdk-0.2.1 → shadowpaysdk-16.7.2025.1}/shadowPaySDK/interface/__init__.py +2 -2
- {shadowpaysdk-0.2.1 → shadowpaysdk-16.7.2025.1}/shadowPaySDK/interface/erc20.py +29 -18
- shadowpaysdk-16.7.2025.1/shadowPaySDK/interface/sol.py +230 -0
- {shadowpaysdk-0.2.1 → shadowpaysdk-16.7.2025.1}/shadowPaySDK/types/EVMcheque.py +166 -74
- shadowpaysdk-16.7.2025.1/shadowPaySDK/types/SOLcheque.py +284 -0
- {shadowpaysdk-0.2.1 → shadowpaysdk-16.7.2025.1}/shadowPaySDK.egg-info/PKG-INFO +20 -7
- shadowpaysdk-16.7.2025.1/shadowPaySDK.egg-info/requires.txt +6 -0
- shadowpaysdk-0.2.1/README.md +0 -8
- shadowpaysdk-0.2.1/shadowPaySDK/interface/sol.py +0 -162
- shadowpaysdk-0.2.1/shadowPaySDK/types/SOLcheque.py +0 -27
- shadowpaysdk-0.2.1/shadowPaySDK.egg-info/requires.txt +0 -6
- {shadowpaysdk-0.2.1 → shadowpaysdk-16.7.2025.1}/LICENSE +0 -0
- {shadowpaysdk-0.2.1 → shadowpaysdk-16.7.2025.1}/setup.cfg +0 -0
- {shadowpaysdk-0.2.1 → shadowpaysdk-16.7.2025.1}/shadowPaySDK/api.py +0 -0
- {shadowpaysdk-0.2.1 → shadowpaysdk-16.7.2025.1}/shadowPaySDK/interface/erc721.py +0 -0
- {shadowpaysdk-0.2.1 → shadowpaysdk-16.7.2025.1}/shadowPaySDK/types/__init__.py +0 -0
- {shadowpaysdk-0.2.1 → shadowpaysdk-16.7.2025.1}/shadowPaySDK/utils/__init__.py +0 -0
- {shadowpaysdk-0.2.1 → shadowpaysdk-16.7.2025.1}/shadowPaySDK/utils/utils.py +0 -0
- {shadowpaysdk-0.2.1 → shadowpaysdk-16.7.2025.1}/shadowPaySDK.egg-info/SOURCES.txt +0 -0
- {shadowpaysdk-0.2.1 → shadowpaysdk-16.7.2025.1}/shadowPaySDK.egg-info/dependency_links.txt +0 -0
- {shadowpaysdk-0.2.1 → shadowpaysdk-16.7.2025.1}/shadowPaySDK.egg-info/top_level.txt +0 -0
@@ -1,8 +1,8 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: shadowPaySDK
|
3
|
-
Version:
|
3
|
+
Version: 16.7.2025.1
|
4
4
|
Summary: ShadowPay SDK for ERC20/ERC721 and P2P smart contract interaction
|
5
|
-
Author: dazarius_
|
5
|
+
Author: dazay(aka dazarius_)
|
6
6
|
Author-email: your@email.com
|
7
7
|
License: MIT
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
@@ -11,10 +11,10 @@ Classifier: Operating System :: OS Independent
|
|
11
11
|
Requires-Python: >=3.9
|
12
12
|
Description-Content-Type: text/markdown
|
13
13
|
License-File: LICENSE
|
14
|
-
Requires-Dist: web3
|
15
|
-
Requires-Dist: requests
|
16
|
-
Requires-Dist: solana
|
17
|
-
Requires-Dist: anchorpy
|
14
|
+
Requires-Dist: web3
|
15
|
+
Requires-Dist: requests
|
16
|
+
Requires-Dist: solana
|
17
|
+
Requires-Dist: anchorpy
|
18
18
|
Requires-Dist: solders
|
19
19
|
Requires-Dist: httpx==0.28.1
|
20
20
|
Dynamic: author
|
@@ -28,11 +28,24 @@ Dynamic: requires-dist
|
|
28
28
|
Dynamic: requires-python
|
29
29
|
Dynamic: summary
|
30
30
|
|
31
|
-
#
|
31
|
+
# shadowPaySdk
|
32
32
|
|
33
33
|
```bash
|
34
34
|
pip3 install shadowPaySDK
|
35
|
+
pip3 install --break-system-packages git+https://github.com/dazarius/SDK.git
|
35
36
|
```
|
37
|
+
```example to use cheque
|
38
|
+
|
39
|
+
|
40
|
+
|
41
|
+
|
42
|
+
|
43
|
+
import shadowPaySDK
|
44
|
+
|
45
|
+
|
46
|
+
EVMcheque = shadowPaySDK.Cheque(
|
47
|
+
retunrn_build_tx=True
|
48
|
+
)
|
36
49
|
|
37
50
|
|
38
51
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# shadowPaySdk
|
2
|
+
|
3
|
+
```bash
|
4
|
+
pip3 install shadowPaySDK
|
5
|
+
pip3 install --break-system-packages git+https://github.com/dazarius/SDK.git
|
6
|
+
```
|
7
|
+
```example to use cheque
|
8
|
+
|
9
|
+
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
import shadowPaySDK
|
14
|
+
|
15
|
+
|
16
|
+
EVMcheque = shadowPaySDK.Cheque(
|
17
|
+
retunrn_build_tx=True
|
18
|
+
)
|
19
|
+
|
20
|
+
|
21
|
+
|
@@ -2,11 +2,11 @@ from setuptools import setup, find_packages
|
|
2
2
|
|
3
3
|
setup(
|
4
4
|
name='shadowPaySDK',
|
5
|
-
version='
|
5
|
+
version='16.07.2025.1',
|
6
6
|
description='ShadowPay SDK for ERC20/ERC721 and P2P smart contract interaction',
|
7
7
|
long_description=open('README.md').read(),
|
8
8
|
long_description_content_type='text/markdown',
|
9
|
-
author='dazarius_',
|
9
|
+
author='dazay(aka dazarius_)',
|
10
10
|
author_email='your@email.com',
|
11
11
|
license='MIT',
|
12
12
|
packages=find_packages(),
|
@@ -16,10 +16,10 @@ setup(
|
|
16
16
|
'Operating System :: OS Independent',
|
17
17
|
],
|
18
18
|
install_requires=[
|
19
|
-
'web3
|
20
|
-
'requests
|
21
|
-
'solana
|
22
|
-
'anchorpy
|
19
|
+
'web3',
|
20
|
+
'requests',
|
21
|
+
'solana',
|
22
|
+
'anchorpy',
|
23
23
|
|
24
24
|
'solders',
|
25
25
|
'httpx==0.28.1'
|
@@ -1,12 +1,10 @@
|
|
1
1
|
import json
|
2
2
|
from shadowPaySDK.interface.erc20 import ERC20Token
|
3
3
|
from shadowPaySDK.interface.erc721 import ERC721Token
|
4
|
-
from shadowPaySDK.interface.sol import
|
5
|
-
from shadowPaySDK.interface.sol import SOL
|
4
|
+
from shadowPaySDK.interface.sol import SOL as sol
|
6
5
|
from shadowPaySDK.types.EVMcheque import Cheque
|
7
6
|
from shadowPaySDK.types.SOLcheque import SOLCheque
|
8
7
|
from shadowPaySDK.const import __ERC20_ABI__, __SHADOWPAY_ABI__ERC20__,__ALLOW_CHAINS__, __SHADOWPAY_CONTRACT_ADDRESS__ERC20__
|
9
|
-
from shadowPaySDK.api import __MAIN__URL__, __CREATE__CHEQUE__, get_my_cheques, create_cheque
|
10
8
|
|
11
9
|
|
12
10
|
# from shadowPaySDK.utils import parse_tx as PARSE_TX
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import json
|
2
|
-
|
2
|
+
from solders.pubkey import Pubkey
|
3
3
|
__ALLOW_CHAINS__ = [
|
4
4
|
56, # BSC Mainnet
|
5
5
|
97, # BSC Testnet
|
@@ -11,6 +11,9 @@ __ALLOW_CHAINS__ = [
|
|
11
11
|
0xa
|
12
12
|
]
|
13
13
|
|
14
|
+
|
15
|
+
|
16
|
+
|
14
17
|
__VERSION__ = "0.1.2"
|
15
18
|
|
16
19
|
|
@@ -27,7 +30,7 @@ __ERC20_ABI__ = json.loads("""[
|
|
27
30
|
]""")
|
28
31
|
|
29
32
|
__SHADOWPAY_CONTRACT_ADDRESS__ERC20__ = {
|
30
|
-
97: "
|
33
|
+
97: "0x5487C0DdCbD5465F26B446c6CAB88D8d6F7DF23b"
|
31
34
|
}
|
32
35
|
|
33
36
|
__SHADOWPAY_ABI__ERC20__= json.loads("""[
|
@@ -543,4 +546,13 @@ __SHADOWPAY_ABI__ERC20__= json.loads("""[
|
|
543
546
|
__SHADOWPAY_ABI__ERC721__ = json.loads("""[]""")
|
544
547
|
__SHADOWPAY_CONTRACT_ADDRESS__ERC721__ = {
|
545
548
|
"0x1": "0x3c5b8d6f2e"
|
546
|
-
}
|
549
|
+
}
|
550
|
+
|
551
|
+
SOLANA_SYSTEM_PROGRAMM = "11111111111111111111111111111111"
|
552
|
+
LAMPORTS_PER_SOL = 1_000_000_000
|
553
|
+
WRAPED_SOL = "So11111111111111111111111111111111111111112"
|
554
|
+
TOKEN_PROGRAM_ID = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
|
555
|
+
NATIVE_DECIMALS: int = 9
|
556
|
+
PROGRAM_ID = Pubkey.from_string("CrfYLvU4FdVjkBno2rRi6u5U6nGCykpQnQKSBg3uVXTw")
|
557
|
+
|
558
|
+
CONFIG_PDA=Pubkey.find_program_address([b"config"], PROGRAM_ID)
|
@@ -6,9 +6,10 @@ from shadowPaySDK.const import __ERC20_ABI__
|
|
6
6
|
|
7
7
|
|
8
8
|
class ERC20Token:
|
9
|
-
def __init__(self, w3:Web3, explorer: Optional[str] = None):
|
9
|
+
def __init__(self, w3: Optional[Web3] = None, explorer: Optional[str] = None):
|
10
10
|
self.web3 = w3
|
11
11
|
self.explorer = explorer
|
12
|
+
|
12
13
|
self.address = None
|
13
14
|
self.contract = None
|
14
15
|
|
@@ -21,7 +22,7 @@ class ERC20Token:
|
|
21
22
|
|
22
23
|
def _ensure_contract(self):
|
23
24
|
if not self.contract:
|
24
|
-
raise ValueError("Token address is not set. Use
|
25
|
+
raise ValueError("Token address is not set. Use set_params first.")
|
25
26
|
|
26
27
|
def _format_tx(self, tx_hash: str) -> str:
|
27
28
|
if self.explorer:
|
@@ -30,10 +31,9 @@ class ERC20Token:
|
|
30
31
|
def gen_wallet(self) -> str:
|
31
32
|
account = self.web3.eth.account.create()
|
32
33
|
return account
|
33
|
-
def get_decimals(self
|
34
|
+
def get_decimals(self) -> int:
|
34
35
|
self._ensure_contract()
|
35
|
-
|
36
|
-
self.set_params(token_address=token)
|
36
|
+
|
37
37
|
return self.contract.functions.decimals().call()
|
38
38
|
|
39
39
|
def get_symbol(self) -> str:
|
@@ -45,21 +45,21 @@ class ERC20Token:
|
|
45
45
|
raw = self.contract.functions.balanceOf(Web3.to_checksum_address(wallet_address)).call()
|
46
46
|
return raw / (10 ** self.get_decimals())
|
47
47
|
|
48
|
-
def allowance(self, owner: str, spender: str
|
48
|
+
def allowance(self, owner: str, spender: str) -> float:
|
49
49
|
self._ensure_contract()
|
50
50
|
raw = self.contract.functions.allowance(
|
51
51
|
Web3.to_checksum_address(owner),
|
52
52
|
Web3.to_checksum_address(spender)
|
53
53
|
).call()
|
54
|
-
return raw / (10 ** self.get_decimals(
|
54
|
+
return raw / (10 ** self.get_decimals())
|
55
55
|
|
56
|
-
def ensure_allowance(self, private_key: str, spender: str, amount
|
56
|
+
def ensure_allowance(self, private_key: str, spender: str, amount) -> Union[bool, str]:
|
57
57
|
self._ensure_contract()
|
58
58
|
account = self.web3.eth.account.from_key(private_key)
|
59
|
-
current = self.allowance(account.address, spender
|
59
|
+
current = self.allowance(account.address, spender)
|
60
60
|
if current == amount:
|
61
61
|
return True
|
62
|
-
return self.approve(private_key, spender, amount
|
62
|
+
return self.approve(private_key, spender, amount)
|
63
63
|
|
64
64
|
def transfer(self, private_key: str, to: str, amount: float) -> str:
|
65
65
|
self._ensure_contract()
|
@@ -87,28 +87,39 @@ class ERC20Token:
|
|
87
87
|
tx_hash = self.web3.eth.send_raw_transaction(signed.raw_transaction)
|
88
88
|
return self._format_tx(self.web3.to_hex(tx_hash))
|
89
89
|
|
90
|
-
def approve(self,
|
90
|
+
def approve(self, spender: str, amount: float,address:Optional[str] = None, private_key: Optional[str] = None, build_tx: bool = False) -> str:
|
91
|
+
|
91
92
|
self._ensure_contract()
|
92
|
-
|
93
|
-
|
93
|
+
key = private_key
|
94
|
+
|
95
|
+
if key:
|
96
|
+
address = Web3.to_checksum_address(self.web3.eth.account.from_key(key).address)
|
97
|
+
|
98
|
+
elif self.address:
|
99
|
+
address = Web3.to_checksum_address(self.address)
|
100
|
+
else:
|
101
|
+
raise ValueError("No private key or address provided")
|
102
|
+
|
103
|
+
decimals = self.get_decimals()
|
94
104
|
amount = int(amount * (10 ** decimals))
|
95
105
|
|
96
106
|
txn = self.contract.functions.approve(
|
97
107
|
Web3.to_checksum_address(spender),
|
98
108
|
amount
|
99
109
|
).build_transaction({
|
100
|
-
'from':
|
101
|
-
'nonce': self.web3.eth.get_transaction_count(
|
110
|
+
'from': address,
|
111
|
+
'nonce': self.web3.eth.get_transaction_count(address),
|
102
112
|
'gas': 60000,
|
103
113
|
|
104
114
|
'gasPrice': self.web3.eth.gas_price,
|
105
115
|
})
|
116
|
+
if build_tx:
|
117
|
+
return txn
|
106
118
|
|
107
|
-
signed = self.web3.eth.account.sign_transaction(txn,
|
119
|
+
signed = self.web3.eth.account.sign_transaction(txn, key)
|
108
120
|
tx_hash = self.web3.eth.send_raw_transaction(signed.raw_transaction)
|
109
121
|
tx_receipt = self.web3.eth.wait_for_transaction_receipt(tx_hash)
|
110
122
|
if tx_receipt.status != 1:
|
111
123
|
raise ValueError(f"aaprove fail.\n {self._format_tx(self.web3.to_hex(tx_hash))}")
|
112
|
-
|
113
|
-
return f"approve: {self._format_tx(self.web3.to_hex(tx_hash))}"
|
124
|
+
return f"{self._format_tx(self.web3.to_hex(tx_hash))}"
|
114
125
|
|
@@ -0,0 +1,230 @@
|
|
1
|
+
import asyncio
|
2
|
+
import solana
|
3
|
+
from solana.rpc.async_api import AsyncClient, GetTokenAccountsByOwnerResp
|
4
|
+
from solders.transaction import Transaction
|
5
|
+
from solders.system_program import TransferParams as p
|
6
|
+
import spl
|
7
|
+
import spl.token
|
8
|
+
import spl.token.constants
|
9
|
+
from spl.token.instructions import get_associated_token_address, create_associated_token_account, transfer, close_account, TransferParams
|
10
|
+
from solders.system_program import transfer as ts
|
11
|
+
from solders.system_program import TransferParams as tsf
|
12
|
+
from spl.token.constants import TOKEN_PROGRAM_ID, ASSOCIATED_TOKEN_PROGRAM_ID
|
13
|
+
from solana.rpc.types import TxOpts, TokenAccountOpts
|
14
|
+
from solana.rpc.types import TxOpts
|
15
|
+
import solders
|
16
|
+
from solders.message import Message
|
17
|
+
|
18
|
+
# from solders.pubkey import Pubkey
|
19
|
+
# from solders.keypair import Keypair
|
20
|
+
# from solders.signature import Signature
|
21
|
+
# from solders.transaction import Transaction
|
22
|
+
from spl.token.async_client import AsyncToken
|
23
|
+
|
24
|
+
|
25
|
+
from solana.rpc.commitment import Confirmed
|
26
|
+
from solana.rpc.async_api import AsyncClient
|
27
|
+
import anchorpy
|
28
|
+
from anchorpy import Provider, Wallet, Idl
|
29
|
+
from typing import Optional, Union
|
30
|
+
import pprint
|
31
|
+
import httpx
|
32
|
+
import base64
|
33
|
+
import re
|
34
|
+
|
35
|
+
|
36
|
+
LAMPORTS_PER_SOL = 1_000_000_000 # 1 SOL = 1,000,000,000 lamports
|
37
|
+
|
38
|
+
class SOL:
|
39
|
+
def __init__(self, rpc_url = "https://api.mainnet-beta.solana.com", KEYPAIR: Optional[Union[str, solders.keypair.Keypair]] = None,TOKEN_MINT: Optional[str] = None):
|
40
|
+
self.rpc_url = rpc_url
|
41
|
+
|
42
|
+
self.client = AsyncClient(rpc_url)
|
43
|
+
self.KEYPAIR = None
|
44
|
+
self.PROGRAM_ID = TOKEN_PROGRAM_ID # Default to the SPL Token Program ID
|
45
|
+
self.TOKEN_MINT = TOKEN_MINT
|
46
|
+
self.WRAPED_SOL_ID = spl.token.constants.WRAPPED_SOL_MINT
|
47
|
+
if KEYPAIR:
|
48
|
+
self.set_keypair(KEYPAIR)
|
49
|
+
|
50
|
+
def set_keypair(self, KEYPAIR: Union[str, solders.keypair.Keypair]):
|
51
|
+
if isinstance(KEYPAIR, str):
|
52
|
+
try:
|
53
|
+
self.KEYPAIR = solders.keypair.Keypair.from_base58_string(KEYPAIR)
|
54
|
+
except Exception as e:
|
55
|
+
raise ValueError(f"Invalid Keypair string: {e}")
|
56
|
+
elif isinstance(KEYPAIR, solders.keypair.Keypair):
|
57
|
+
self.KEYPAIR = KEYPAIR
|
58
|
+
else:
|
59
|
+
raise ValueError("KEYPAIR must be a Keypair instance or a base58 encoded string.")
|
60
|
+
|
61
|
+
def set_params(self, rpc_url: Optional[str] = None, KEYPAIR: Optional[Union[str, solders.keypair.Keypair]] = None,TOKEN_MINT: Optional[str] = None):
|
62
|
+
if rpc_url:
|
63
|
+
self.rpc_url = rpc_url
|
64
|
+
self.client = AsyncClient(rpc_url)
|
65
|
+
if KEYPAIR:
|
66
|
+
self.set_keypair(KEYPAIR)
|
67
|
+
if TOKEN_MINT:
|
68
|
+
self.TOKEN_MINT = TOKEN_MINT
|
69
|
+
|
70
|
+
def get_pubkey(self, returnString: Optional[bool] = None):
|
71
|
+
|
72
|
+
|
73
|
+
if self.KEYPAIR:
|
74
|
+
pubkey = self.KEYPAIR.pubkey()
|
75
|
+
pubkey_str = str(pubkey)
|
76
|
+
if returnString:
|
77
|
+
return pubkey_str
|
78
|
+
return pubkey
|
79
|
+
|
80
|
+
raise ValueError("Keypair not set")
|
81
|
+
|
82
|
+
def gen_wallet(self):
|
83
|
+
return solders.keypair.Keypair()
|
84
|
+
async def get_balance(self):
|
85
|
+
resp = await self.client.get_balance(self.get_pubkey())
|
86
|
+
lamports = resp.value
|
87
|
+
sol_balance = lamports / LAMPORTS_PER_SOL
|
88
|
+
return sol_balance
|
89
|
+
async def get_token_accounts_by_owner(self,owner_pubkey: Optional[str] = None):
|
90
|
+
if not owner_pubkey:
|
91
|
+
print("No owner pubkey provided, using the wallet's pubkey.")
|
92
|
+
owner_pubkey = self.get_pubkey(returnString=True)
|
93
|
+
headers = {
|
94
|
+
"Content-Type": "application/json",
|
95
|
+
}
|
96
|
+
body = {
|
97
|
+
"jsonrpc": "2.0",
|
98
|
+
"id": 1,
|
99
|
+
"method": "getTokenAccountsByOwner",
|
100
|
+
"params": [
|
101
|
+
str(owner_pubkey),
|
102
|
+
{"programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"},
|
103
|
+
{"encoding": "jsonParsed"}
|
104
|
+
]
|
105
|
+
}
|
106
|
+
async with httpx.AsyncClient() as client:
|
107
|
+
response = await client.post(self.rpc_url, headers=headers, json=body)
|
108
|
+
result = response.json()
|
109
|
+
accounts = result["result"]["value"]
|
110
|
+
|
111
|
+
token_data = {}
|
112
|
+
for acc in accounts:
|
113
|
+
parsed = acc["account"]["data"]["parsed"]["info"]
|
114
|
+
mint = parsed["mint"]
|
115
|
+
ui_amount = parsed["tokenAmount"]["uiAmount"]
|
116
|
+
token_data[mint] = {"amount": ui_amount}
|
117
|
+
|
118
|
+
|
119
|
+
|
120
|
+
return token_data
|
121
|
+
async def is_connected(self):
|
122
|
+
return await self.client.is_connected()
|
123
|
+
|
124
|
+
async def close(self):
|
125
|
+
await self.client.close()
|
126
|
+
|
127
|
+
async def fetch_metadata_raw(self,mint_address: str):
|
128
|
+
METADATA_PROGRAM_ID = solders.pubkey.Pubkey.from_string("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s")
|
129
|
+
mint = solders.pubkey.Pubkey.from_string(mint_address)
|
130
|
+
seeds = [
|
131
|
+
b"metadata",
|
132
|
+
bytes(METADATA_PROGRAM_ID),
|
133
|
+
bytes(mint),
|
134
|
+
]
|
135
|
+
pda, _ = solders.pubkey.Pubkey.find_program_address(seeds, METADATA_PROGRAM_ID)
|
136
|
+
|
137
|
+
payload = {
|
138
|
+
"jsonrpc": "2.0",
|
139
|
+
"id": 1,
|
140
|
+
"method": "getAccountInfo",
|
141
|
+
"params": [
|
142
|
+
str(pda),
|
143
|
+
{"encoding": "base64"}
|
144
|
+
]
|
145
|
+
}
|
146
|
+
|
147
|
+
async with httpx.AsyncClient() as client:
|
148
|
+
r = await client.post(self.rpc_url, json=payload)
|
149
|
+
data = r.json()
|
150
|
+
|
151
|
+
if not data["result"]["value"]:
|
152
|
+
return None
|
153
|
+
|
154
|
+
b64_data = data["result"]["value"]["data"][0]
|
155
|
+
raw_bytes = base64.b64decode(b64_data)
|
156
|
+
|
157
|
+
name = raw_bytes[1+32+32 : 1+32+32+32].decode("utf-8").rstrip("\x00")
|
158
|
+
name = re.sub(r'[^\x20-\x7E]', '', name)
|
159
|
+
return {
|
160
|
+
"mint": mint_address,
|
161
|
+
"name": name,
|
162
|
+
|
163
|
+
|
164
|
+
}
|
165
|
+
async def transfer_token(self, to: str, amount: float):
|
166
|
+
|
167
|
+
if not self.TOKEN_MINT:
|
168
|
+
raise ValueError("not set TOKEN_MINT.")
|
169
|
+
if not self.KEYPAIR:
|
170
|
+
raise ValueError("not set KEYPAIR.")
|
171
|
+
|
172
|
+
sender_pubkey = self.get_pubkey()
|
173
|
+
receiver_pubkey = solders.pubkey.Pubkey.from_string(to)
|
174
|
+
token_pubkey = solders.pubkey.Pubkey.from_string(self.TOKEN_MINT)
|
175
|
+
|
176
|
+
token = AsyncToken(self.client, token_pubkey, TOKEN_PROGRAM_ID, self.KEYPAIR)
|
177
|
+
sender_ata = get_associated_token_address(sender_pubkey, token_pubkey)
|
178
|
+
receiver_ata = get_associated_token_address(receiver_pubkey, token_pubkey)
|
179
|
+
|
180
|
+
tx = Transaction()
|
181
|
+
|
182
|
+
res = await self.client.get_account_info(receiver_ata)
|
183
|
+
if res.value is None:
|
184
|
+
tx.add(
|
185
|
+
create_associated_token_account(
|
186
|
+
payer=sender_pubkey,
|
187
|
+
owner=receiver_pubkey,
|
188
|
+
mint=token_pubkey
|
189
|
+
)
|
190
|
+
)
|
191
|
+
|
192
|
+
decimals = (await token.get_mint_info()).decimals
|
193
|
+
real_amount = int(amount * (10 ** decimals))
|
194
|
+
params = TransferParams(
|
195
|
+
program_id=TOKEN_PROGRAM_ID,
|
196
|
+
source=sender_ata,
|
197
|
+
dest=receiver_ata,
|
198
|
+
owner=sender_pubkey,
|
199
|
+
amount=real_amount
|
200
|
+
)
|
201
|
+
|
202
|
+
tx.add(transfer(params))
|
203
|
+
|
204
|
+
resp = await self.client.send_transaction(tx, self.KEYPAIR, opts=TxOpts(skip_preflight=True, preflight_commitment=Confirmed))
|
205
|
+
return resp.value
|
206
|
+
|
207
|
+
|
208
|
+
async def transfer_native(self, to:str, amount: int):
|
209
|
+
if not self.KEYPAIR:
|
210
|
+
raise ValueError("not set KEYPAIR.")
|
211
|
+
|
212
|
+
sender_pubkey = self.get_pubkey()
|
213
|
+
receiver_pubkey = solders.pubkey.Pubkey.from_string(to)
|
214
|
+
ixns = [
|
215
|
+
ts(tsf(
|
216
|
+
from_pubkey=sender_pubkey,
|
217
|
+
to_pubkey=receiver_pubkey,
|
218
|
+
lamports=int(amount * LAMPORTS_PER_SOL)
|
219
|
+
))
|
220
|
+
]
|
221
|
+
msg = Message(ixns, self.get_pubkey())
|
222
|
+
latest_blockhash_resp = await self.client.get_latest_blockhash()
|
223
|
+
|
224
|
+
blockhash_str = latest_blockhash_resp.value.blockhash
|
225
|
+
tx = Transaction([self.KEYPAIR], msg, blockhash_str)
|
226
|
+
resp = await self.client.send_transaction(tx)
|
227
|
+
return resp.value
|
228
|
+
|
229
|
+
|
230
|
+
|