shadowPaySDK 0.2.1__py3-none-any.whl → 16.7.2025.1__py3-none-any.whl

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/__init__.py CHANGED
@@ -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 SolTokens
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
shadowPaySDK/const.py CHANGED
@@ -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: "0x17a82E53a3b3f2acA7ceae8CA6B6b3B8F14e4441"
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)
@@ -1,4 +1,4 @@
1
1
  from .erc20 import ERC20Token as ERC20
2
2
  from .erc721 import ERC721Token as ERC721
3
- from .sol import SolTokens as SPL
4
- __all__ = ["ERC20", "ERC721", "SPL"]
3
+ from .sol import SOL as sol
4
+ __all__ = ["ERC20", "ERC721", "sol"]
@@ -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 set_token(token_address) first.")
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, token) -> int:
34
+ def get_decimals(self) -> int:
34
35
  self._ensure_contract()
35
- if token:
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, token) -> float:
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(token))
54
+ return raw / (10 ** self.get_decimals())
55
55
 
56
- def ensure_allowance(self, private_key: str, spender: str, amount, token) -> Union[bool, str]:
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, token)
59
+ current = self.allowance(account.address, spender)
60
60
  if current == amount:
61
61
  return True
62
- return self.approve(private_key, spender, amount, token)
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, private_key: str, spender: str, amount: float, token) -> str:
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
- account = self.web3.eth.account.from_key(private_key)
93
- decimals = self.get_decimals(token=token)
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': account.address,
101
- 'nonce': self.web3.eth.get_transaction_count(account.address),
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, private_key)
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
 
@@ -1,17 +1,29 @@
1
1
  import asyncio
2
+ import solana
2
3
  from solana.rpc.async_api import AsyncClient, GetTokenAccountsByOwnerResp
4
+ from solders.transaction import Transaction
5
+ from solders.system_program import TransferParams as p
3
6
  import spl
4
7
  import spl.token
5
8
  import spl.token.constants
6
- from spl.token.instructions import get_associated_token_address, create_associated_token_account, transfer, close_account
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
7
12
  from spl.token.constants import TOKEN_PROGRAM_ID, ASSOCIATED_TOKEN_PROGRAM_ID
8
- from solana.constants import *
9
13
  from solana.rpc.types import TxOpts, TokenAccountOpts
10
14
  from solana.rpc.types import TxOpts
11
15
  import solders
12
- from solders.pubkey import Pubkey
13
- from solders.keypair import Keypair
14
- from solders.signature import Signature
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
15
27
  import anchorpy
16
28
  from anchorpy import Provider, Wallet, Idl
17
29
  from typing import Optional, Union
@@ -20,44 +32,40 @@ import httpx
20
32
  import base64
21
33
  import re
22
34
 
23
- class SolTokens:
24
- def __init__(self, rpc_url: str = "https://api.mainnet-beta.solana.com"):
25
- self.rpc_url = rpc_url
26
- self.client = AsyncClient(rpc_url)
27
- self.PROGRAM_ID = TOKEN_PROGRAM_ID # Default to the SPL Token Program ID
28
- self.WRAPED_SOL_ID = spl.token.constants.WRAPPED_SOL_MINT
29
- def set_params(self, rpc_url: Optional[str] = None, PROGRAM_ID: Optional[str] = None):
30
- if rpc_url:
31
- self.rpc_url = rpc_url
32
- self.client = AsyncClient(rpc_url)
35
+
36
+ LAMPORTS_PER_SOL = 1_000_000_000 # 1 SOL = 1,000,000,000 lamports
33
37
 
34
38
  class SOL:
35
-
36
- def __init__(self, rpc_url = "https://api.mainnet-beta.solana.com", KEYPAIR: Optional[Union[str, Keypair]] = None):
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):
37
40
  self.rpc_url = rpc_url
41
+
38
42
  self.client = AsyncClient(rpc_url)
39
43
  self.KEYPAIR = None
40
-
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
41
47
  if KEYPAIR:
42
48
  self.set_keypair(KEYPAIR)
43
49
 
44
- def set_keypair(self, KEYPAIR: Union[str, Keypair]):
50
+ def set_keypair(self, KEYPAIR: Union[str, solders.keypair.Keypair]):
45
51
  if isinstance(KEYPAIR, str):
46
52
  try:
47
- self.KEYPAIR = Keypair.from_base58_string(KEYPAIR)
53
+ self.KEYPAIR = solders.keypair.Keypair.from_base58_string(KEYPAIR)
48
54
  except Exception as e:
49
55
  raise ValueError(f"Invalid Keypair string: {e}")
50
- elif isinstance(KEYPAIR, Keypair):
56
+ elif isinstance(KEYPAIR, solders.keypair.Keypair):
51
57
  self.KEYPAIR = KEYPAIR
52
58
  else:
53
59
  raise ValueError("KEYPAIR must be a Keypair instance or a base58 encoded string.")
54
60
 
55
- def set_params(self, rpc_url: Optional[str] = None, KEYPAIR: Optional[Union[str, Keypair]] = None):
61
+ def set_params(self, rpc_url: Optional[str] = None, KEYPAIR: Optional[Union[str, solders.keypair.Keypair]] = None,TOKEN_MINT: Optional[str] = None):
56
62
  if rpc_url:
57
63
  self.rpc_url = rpc_url
58
64
  self.client = AsyncClient(rpc_url)
59
65
  if KEYPAIR:
60
66
  self.set_keypair(KEYPAIR)
67
+ if TOKEN_MINT:
68
+ self.TOKEN_MINT = TOKEN_MINT
61
69
 
62
70
  def get_pubkey(self, returnString: Optional[bool] = None):
63
71
 
@@ -72,7 +80,7 @@ class SOL:
72
80
  raise ValueError("Keypair not set")
73
81
 
74
82
  def gen_wallet(self):
75
- return Keypair()
83
+ return solders.keypair.Keypair()
76
84
  async def get_balance(self):
77
85
  resp = await self.client.get_balance(self.get_pubkey())
78
86
  lamports = resp.value
@@ -107,9 +115,9 @@ class SOL:
107
115
  ui_amount = parsed["tokenAmount"]["uiAmount"]
108
116
  token_data[mint] = {"amount": ui_amount}
109
117
 
110
- filtered = {mint: data for mint, data in token_data.items() if data["amount"] > 0.001}
118
+
111
119
 
112
- return filtered
120
+ return token_data
113
121
  async def is_connected(self):
114
122
  return await self.client.is_connected()
115
123
 
@@ -117,14 +125,14 @@ class SOL:
117
125
  await self.client.close()
118
126
 
119
127
  async def fetch_metadata_raw(self,mint_address: str):
120
- METADATA_PROGRAM_ID = Pubkey.from_string("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s")
121
- mint = Pubkey.from_string(mint_address)
128
+ METADATA_PROGRAM_ID = solders.pubkey.Pubkey.from_string("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s")
129
+ mint = solders.pubkey.Pubkey.from_string(mint_address)
122
130
  seeds = [
123
131
  b"metadata",
124
132
  bytes(METADATA_PROGRAM_ID),
125
133
  bytes(mint),
126
134
  ]
127
- pda, _ = Pubkey.find_program_address(seeds, METADATA_PROGRAM_ID)
135
+ pda, _ = solders.pubkey.Pubkey.find_program_address(seeds, METADATA_PROGRAM_ID)
128
136
 
129
137
  payload = {
130
138
  "jsonrpc": "2.0",
@@ -137,7 +145,7 @@ class SOL:
137
145
  }
138
146
 
139
147
  async with httpx.AsyncClient() as client:
140
- r = await client.post("https://api.mainnet-beta.solana.com", json=payload)
148
+ r = await client.post(self.rpc_url, json=payload)
141
149
  data = r.json()
142
150
 
143
151
  if not data["result"]["value"]:
@@ -151,12 +159,72 @@ class SOL:
151
159
  return {
152
160
  "mint": mint_address,
153
161
  "name": name,
154
- }
162
+
155
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()
156
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
157
228
 
158
229
 
159
230
 
160
- if __name__ == "__main__":
161
- newKeypair = Keypair()
162
- print("New Keypair:", newKeypair)
@@ -7,20 +7,27 @@ import httpx
7
7
 
8
8
 
9
9
  class Cheque:
10
- def __init__(self, w3:Web3,private_key:str, ABI = __SHADOWPAY_ABI__ERC20__, allowed_chains = __ALLOW_CHAINS__):
10
+ def __init__(self, w3:Optional[Web3] = None,private_key:Optional[str] = None, ABI = __SHADOWPAY_ABI__ERC20__, allowed_chains = __ALLOW_CHAINS__, retunrn_build_tx:bool = False,address:Optional[str] = None):
11
11
  self.w3 = w3
12
- print(f"chain id: {self.w3.eth.chain_id}")
13
- print(f"allowed chains", allowed_chains)
12
+
14
13
  self.amount = None
15
14
  self.token = None
16
15
  self.private_key = private_key
17
16
  self.ABI = ABI
18
-
17
+ self.address = address
18
+ self.return_build_tx = retunrn_build_tx
19
19
  self.allowed_chains = allowed_chains
20
- if self.__allow__():
21
- print(f"Allowed chains: {self.allowed_chains}")
20
+ if self.w3 != None:
21
+ self.__allow__()
22
+
23
+ def get_id(self, tx):
24
+ if isinstance(tx, str):
25
+ try:
26
+ tx = self.w3.eth.wait_for_transaction_receipt(tx)
27
+ except Exception as e:
28
+ print(f"Failed to get transaction receipt: {str(e)}")
29
+ return False
22
30
 
23
- def __get__id(self, tx):
24
31
  try:
25
32
  logs = self.contract.events.ChequeCreated().process_receipt(tx)
26
33
  cheque_id = logs[0]["args"]["id"]
@@ -40,17 +47,15 @@ class Cheque:
40
47
  def get_contract_for_chain(self,chain_id: str):
41
48
  c = None
42
49
  for chain in __SHADOWPAY_CONTRACT_ADDRESS__ERC20__ :
43
- print(f"Checking chain {chain} against {self.w3.eth.chain_id}")
44
50
  if str(chain) == str(chain_id):
45
51
  c = __SHADOWPAY_CONTRACT_ADDRESS__ERC20__[chain_id]
46
- print(f"Contract address: {c}, type {type(c)} ")
47
52
  contract_address = Web3.to_checksum_address(c)
48
53
  contract = self.w3.eth.contract(address=contract_address, abi=__SHADOWPAY_ABI__ERC20__)
49
54
  self.contract = contract
50
55
  return contract
51
56
  raise ValueError(f"Chain {chain_id} is not supported. Supported chains are: {list(__SHADOWPAY_CONTRACT_ADDRESS__ERC20__.keys())}")
52
57
 
53
- def set_parameters(self,chain_id: Optional[str] = None, w3:Optional[Web3] = None, amount:Optional[int] = None, private_key:Optional[str] = None, token:Optional[str] = None):
58
+ def set_parameters(self,chain_id: Optional[str] = None, w3:Optional[Web3] = None, amount:Optional[int] = None, private_key:Optional[str] = None, token:Optional[str] = None,address:Optional[str] = None):
54
59
  if w3:
55
60
  self.w3 = w3
56
61
  self.get_contract_for_chain(chain_id=chain_id or self.w3.eth.chain_id)
@@ -60,38 +65,63 @@ class Cheque:
60
65
  self.private_key = private_key
61
66
  if token:
62
67
  self.token = token
68
+ if address:
69
+ self.address = address
70
+
63
71
  def __convert__(self):
64
72
  return self.w3.to_wei(self.amount, 'ether')
65
73
 
66
74
  async def InitCheque(self, amount, receiver:list, private_key:Optional[str] = None):
67
75
  if not isinstance(receiver,list):
68
76
  raise ValueError("Receiver must be a list of addresses, [""0x1234...5678", "0x2345...6789""]")
77
+
78
+ key = private_key or self.private_key
79
+
80
+ if key:
81
+ address = Web3.to_checksum_address(self.w3.eth.account.from_key(key).address)
82
+ print("InitCheque", amount, receiver, key)
69
83
 
84
+ elif self.address:
85
+ address = Web3.to_checksum_address(self.address)
86
+ else:
87
+ raise ValueError("No private key or address provided")
88
+
89
+
90
+
91
+
92
+
70
93
  receiver = [Web3.to_checksum_address(addr) for addr in receiver]
71
94
  estimated_gas = self.contract.functions.InitCheque(receiver).estimate_gas({
72
- 'from': self.w3.eth.account.from_key(private_key or self.private_key).address,
95
+ 'from': address,
73
96
  'value': self.w3.to_wei(amount, 'ether'),
74
97
  'gasPrice': self.w3.eth.gas_price
75
98
  })
76
99
  txn = self.contract.functions.InitCheque(receiver).build_transaction({
77
- 'from': self.w3.eth.account.from_key(private_key or self.private_key).address,
100
+ 'from': address,
78
101
  'value': self.w3.to_wei(amount, 'ether'),
79
102
  'nonce': self.w3.eth.get_transaction_count(
80
- self.w3.eth.account.from_key(private_key or self.private_key).address
103
+ address
81
104
  ),
82
105
  'gas': estimated_gas,
83
106
  'gasPrice': self.w3.eth.gas_price,
84
107
  'chainId': self.w3.eth.chain_id
85
108
  })
86
- signed_txn = self.w3.eth.account.sign_transaction(txn, private_key or self.private_key)
109
+ if self.return_build_tx:
110
+ return {
111
+ "build_tx": txn
112
+ }
113
+
114
+ signed_txn = self.w3.eth.account.sign_transaction(txn, key)
87
115
  txn_hash = self.w3.eth.send_raw_transaction(signed_txn.raw_transaction)
88
116
  txn_receipt = self.w3.eth.wait_for_transaction_receipt(txn_hash)
89
117
  insert_to_dn = None
90
- logs = self.__get__id(txn_receipt)
118
+ logs = self.get_id(txn_receipt)
91
119
  if logs:
92
120
  cheque_id = logs
93
121
  else:
94
122
  cheque_id = None
123
+ if txn_receipt.status != 1:
124
+ return False
95
125
  return {
96
126
  "hash": txn_hash.hex(),
97
127
  "chequeId": cheque_id,
@@ -110,49 +140,63 @@ class Cheque:
110
140
 
111
141
 
112
142
  account = self.w3.eth.account.from_key(private_key)
113
- sender_address = account.address
143
+ sender_address = account.address or self.address
114
144
 
115
145
 
116
- # подготовка транзакции
117
- nonce = self.eth.get_transaction_count(sender_address)
146
+ nonce = self.w3.eth.get_transaction_count(sender_address)
118
147
 
119
148
  txn = self.contract.functions.CashOutCheque(
120
149
  Web3.to_bytes(hexstr=cheque_id)).build_transaction({
121
150
  'from': sender_address,
122
151
  'nonce': nonce,
123
- 'gas': 300_000, # пример
152
+ 'gas': 300_000,
124
153
  'gasPrice': self.w3.to_wei('5', 'gwei'),
125
154
  })
155
+ if self.return_build_tx:
156
+ return {
157
+ "build_tx": txn
158
+ }
126
159
 
127
- # подписываем
128
160
  signed_txn = self.w3.eth.account.sign_transaction(txn, private_key=private_key)
129
161
 
130
- # отправляем
162
+
131
163
  tx_hash = self.w3.eth.send_raw_transaction(signed_txn.raw_transaction)
132
164
 
133
- print(f"⏳ Transaction sent: {tx_hash.hex()}")
134
165
  receipt = self.w3.eth.wait_for_transaction_receipt(tx_hash)
135
- print(f"✅ Transaction confirmed in block {receipt.blockNumber}")
136
- return receipt
166
+ if receipt.status != 1:
167
+ return False
168
+ return {
169
+ "hash": tx_hash.hex()
170
+ }
137
171
 
138
172
  async def InitTokenCheque(self, token_address:str, amount, reciver:str, private_key:Optional[str] = None):
139
- # collectedFes
173
+ key = private_key or self.private_key
174
+
175
+ if key:
176
+ address = Web3.to_checksum_address(self.w3.eth.account.from_key(key).address)
177
+
178
+ elif self.address:
179
+ address = Web3.to_checksum_address(self.address)
180
+ else:
181
+ raise ValueError("No private key or address provided")
182
+
183
+
184
+
185
+
140
186
 
141
187
  erc20 = shadowPaySDK.ERC20Token(w3=self.w3)
142
188
  erc20.set_params(token_address=token_address)
143
- ensure_allowance = erc20.ensure_allowance(
144
- private_key=self.private_key,
189
+ decimals = erc20.get_decimals()
190
+ erc20.allowance(
145
191
  spender=self.contract.address,
146
- amount=amount
192
+ owner=address,
147
193
  )
148
- print(f"Ensure allowance: {ensure_allowance}")
149
- decimals = erc20.get_decimals()
150
194
  estimated_gas = self.contract.functions.InitTokenCheque(
151
195
  Web3.to_checksum_address(token_address),
152
196
  int(amount * (10 ** decimals)),
153
197
  Web3.to_checksum_address(reciver)
154
198
  ).estimate_gas({
155
- 'from': self.w3.eth.account.from_key(self.private_key).address,
199
+ 'from': address,
156
200
  'gasPrice': self.w3.eth.gas_price
157
201
  })
158
202
  txn = self.contract.functions.InitTokenCheque(
@@ -160,21 +204,26 @@ class Cheque:
160
204
  int(amount * (10 ** decimals)),
161
205
  Web3.to_checksum_address(reciver)
162
206
  ).build_transaction({
163
- 'from': self.w3.eth.account.from_key(self.private_key).address,
164
- 'nonce': self.w3.eth.get_transaction_count(self.w3.eth.account.from_key(self.private_key).address),
207
+ 'from': address,
208
+ 'nonce': self.w3.eth.get_transaction_count(address),
165
209
  'gas': estimated_gas,
166
210
  'gasPrice': self.w3.eth.gas_price
167
211
  })
168
- signed_txn = self.w3.eth.account.sign_transaction(txn, self.private_key)
212
+ if self.return_build_tx:
213
+ return {
214
+ "build_tx": txn
215
+ }
216
+ signed_txn = self.w3.eth.account.sign_transaction(txn, key)
169
217
  txn_hash = self.w3.eth.send_raw_transaction(signed_txn.raw_transaction)
170
218
  txn_receipt = self.w3.eth.wait_for_transaction_receipt(txn_hash)
171
219
 
172
- logs = self.__get__id(txn_receipt)
220
+ logs = self.get_id(txn_receipt)
173
221
  if logs:
174
222
  cheque_id = logs
175
223
  else:
176
224
  cheque_id = None
177
-
225
+ if txn_receipt.status != 1:
226
+ return False
178
227
  return {
179
228
  "hash": txn_hash.hex(),
180
229
  "chequeId": cheque_id,
@@ -188,46 +237,51 @@ class Cheque:
188
237
 
189
238
 
190
239
 
191
- # Строим транзакцию
192
240
  estimated_gas = self.contract.functions.CashOutTokenCheque(
193
- Web3.to_bytes(hexstr=cheque_id) # Преобразуем строку в bytes32
241
+ Web3.to_bytes(hexstr=cheque_id)
194
242
  ).estimate_gas({
195
- 'from': account.address,
243
+ 'from': account.address or self.address,
196
244
  'gasPrice': self.w3.eth.gas_price
197
245
  })
198
246
  txn = self.contract.functions.CashOutTokenCheque(
199
247
  Web3.to_bytes(hexstr=cheque_id)
200
248
  ).build_transaction({
201
- 'from': account.address,
202
- 'nonce': self.w3.eth.get_transaction_count(account.address),
249
+ 'from': account.address or self.address,
250
+ 'nonce': self.w3.eth.get_transaction_count(account.address or self.address),
203
251
  'gas': estimated_gas,
204
252
  'gasPrice': self.w3.eth.gas_price,
205
253
  })
254
+ if self.return_build_tx:
255
+ return {
256
+ "build_tx": txn
257
+ }
206
258
 
207
- # Подписываем и отправляем транзакцию
208
259
  signed_txn = self.w3.eth.account.sign_transaction(txn, private_key=private_key)
209
260
  tx_hash = self.w3.eth.send_raw_transaction(signed_txn.raw_transaction)
210
261
 
211
- # Получаем подтверждение
212
262
  receipt = self.w3.eth.wait_for_transaction_receipt(tx_hash)
213
263
 
264
+ if receipt.status != 1:
265
+ return False
214
266
  return {
215
267
  "hash": tx_hash.hex(),
216
268
  "status": receipt.status # 1 = success, 0 = fail
217
269
  }
218
270
  async def InitTokenChequeSwap(self, token_in:str, amount_in,token_out:str, amount_out, reciver:str, private_key:Optional[str] = None):
219
-
271
+ key = private_key or self.private_key
272
+ if key:
273
+ address = Web3.to_checksum_address(self.w3.eth.account.from_key(key).address)
274
+ elif self.address:
275
+ address = Web3.to_checksum_address(self.address)
220
276
  erc20 = shadowPaySDK.ERC20Token(w3=self.w3)
221
277
  erc20.set_params(token_address=token_in)
222
- ensure_allowance = erc20.approve(
223
- private_key=self.private_key,
278
+ approve = erc20.allowance(
224
279
  spender=self.contract.address,
225
- amount=amount_in,
226
- token=token_in
280
+ owner=address,
227
281
  )
228
- print(f"Ensure allowance: {ensure_allowance}")
229
- decimals = erc20.get_decimals(token_in)
230
- token_out_decinals = erc20.get_decimals(token_out)
282
+ decimals = erc20.get_decimals()
283
+ erc20.set_params(token_address=token_out)
284
+ token_out_decinals = erc20.get_decimals()
231
285
  estimated_gas = self.contract.functions.InitSwapCheque(
232
286
  Web3.to_checksum_address(reciver),
233
287
  Web3.to_checksum_address(token_in),
@@ -235,7 +289,7 @@ class Cheque:
235
289
  Web3.to_checksum_address(token_out),
236
290
  int(amount_out * (10 ** token_out_decinals)),
237
291
  ).estimate_gas({
238
- 'from': self.w3.eth.account.from_key(self.private_key).address,
292
+ 'from': address,
239
293
  'gasPrice': self.w3.eth.gas_price
240
294
  })
241
295
  txn = self.contract.functions.InitSwapCheque(
@@ -245,24 +299,75 @@ class Cheque:
245
299
  Web3.to_checksum_address(token_out),
246
300
  int(amount_out * (10 ** token_out_decinals))
247
301
  ).build_transaction({
248
- 'from': self.w3.eth.account.from_key(self.private_key).address,
249
- 'nonce': self.w3.eth.get_transaction_count(self.w3.eth.account.from_key(self.private_key).address),
302
+ 'from': address,
303
+ 'nonce': self.w3.eth.get_transaction_count(address),
250
304
  'gas': estimated_gas,
251
305
  'gasPrice': self.w3.eth.gas_price
252
306
  })
253
- signed_txn = self.w3.eth.account.sign_transaction(txn, self.private_key)
307
+ if self.return_build_tx:
308
+ return {
309
+ "build_tx": txn
310
+ }
311
+ signed_txn = self.w3.eth.account.sign_transaction(txn, key)
254
312
  txn_hash = self.w3.eth.send_raw_transaction(signed_txn.raw_transaction)
255
313
  txn_receipt = self.w3.eth.wait_for_transaction_receipt(txn_hash)
256
314
 
257
- logs = self.__get__id(txn_receipt)
315
+ logs = self.get_id(txn_receipt)
258
316
  if logs:
259
317
  cheque_id = logs
260
318
  else:
261
319
  cheque_id = None
320
+ if txn_receipt.status != 1:
321
+ return False
262
322
  return {
263
323
  "hash": txn_hash.hex(),
264
324
  "chequeId": cheque_id
265
325
  }
326
+
327
+ async def CashOutSwapCheque(self, cheque_id: str, private_key: Optional[str] = None):
328
+ swapDetail = await self.getSwaoDetail(cheque_id)
329
+ print(swapDetail)
330
+ if private_key is None:
331
+ private_key = self.private_key
332
+ token_out = swapDetail["tokenOut"]
333
+ amount_out = swapDetail["amountOut"]
334
+ erc20 = shadowPaySDK.ERC20Token(w3=self.w3)
335
+ erc20.set_params(token_address=token_out)
336
+ encure_allowance = erc20.ensure_allowance(
337
+ private_key=private_key,
338
+ spender=self.contract.address,
339
+ amount=amount_out,
340
+ )
341
+ estimated_gas = self.contract.functions.CashOutSwapCheque(
342
+ Web3.to_bytes(hexstr=cheque_id)
343
+ ).estimate_gas({
344
+ 'from': self.w3.eth.account.from_key(private_key).address,
345
+ 'gasPrice': self.w3.eth.gas_price
346
+ })
347
+ swa = self.contract.functions.CashOutSwapCheque(
348
+ Web3.to_bytes(hexstr=cheque_id)
349
+ ).build_transaction({
350
+ 'from': self.w3.eth.account.from_key(private_key).address,
351
+ 'nonce': self.w3.eth.get_transaction_count(self.w3.eth.account.from_key(private_key).address),
352
+ 'gas': 300_000,
353
+ 'gasPrice': self.w3.eth.gas_price
354
+ })
355
+ if self.return_build_tx:
356
+ return {
357
+ "build_tx": swa
358
+ }
359
+ signed_txn = self.w3.eth.account.sign_transaction(swa, private_key=private_key)
360
+ tx_hash = self.w3.eth.send_raw_transaction(signed_txn.raw_transaction)
361
+ receipt = self.w3.eth.wait_for_transaction_receipt(tx_hash)
362
+ if receipt.status != 1:
363
+ return False
364
+ return {
365
+ "hash": tx_hash.hex(),
366
+ }
367
+
368
+
369
+
370
+
266
371
  async def getComunityPool(self):
267
372
  # fee = self.contract.functions.getCollectedFee().call()
268
373
  fee = 50000000000000
@@ -274,7 +379,11 @@ class Cheque:
274
379
  return self.contract.functions.getTreasery().call()
275
380
  async def getSwaoDetail(self, cheque_id: str):
276
381
  cheque_id_bytes = Web3.to_bytes(hexstr=cheque_id)
277
- return self.contract.functions.getSwapDetail(cheque_id_bytes).call()
382
+ s = self.contract.functions.getSwapDetail(cheque_id_bytes).call()
383
+ return{
384
+ "tokenOut": s[0],
385
+ "amountOut": s[1],
386
+ }
278
387
  class NFTcheque:
279
388
  def __init__(self, w3:Web3, token:str, amount:int, spender:str):
280
389
  self.w3 = w3
@@ -306,20 +415,3 @@ class NFTcheque:
306
415
 
307
416
 
308
417
 
309
- async def create_cheque(id, type, chain_id, receiver, sender):
310
- async with httpx.AsyncClient() as client:
311
- response = await client.post(
312
- __CREATE__CHEQUE__,
313
- json={
314
- "cheque_id": id,
315
- "chain_id":chain_id,
316
- "receiver": receiver,
317
- "type": type,
318
- "sender":sender
319
- }
320
- )
321
- if response.status_code == 200:
322
- return response.json()
323
- else:
324
- print(f"Failed to create cheque: {response.text}")
325
- return False
@@ -1,27 +1,284 @@
1
1
 
2
2
  import anchorpy
3
3
  from anchorpy import Idl, Provider, Wallet
4
+ import solders
4
5
  from shadowPaySDK.interface.sol import SOL
5
- from solders.keypair import Keypair
6
- import solana.constants as constants
7
- import solana.constants as sol_constants
6
+ import solders
8
7
  import spl.token.constants as spl_constants
8
+ from solana.rpc.api import Client
9
+
10
+ import asyncio
11
+ import solana
12
+ from solana.rpc.async_api import AsyncClient, GetTokenAccountsByOwnerResp
13
+ from solders.transaction import Transaction
14
+ from solders.system_program import TransferParams as p
15
+ from solders.instruction import Instruction, AccountMeta
16
+ from solders.rpc.config import RpcSendTransactionConfig
17
+ from solders.message import Message
18
+ import spl
19
+ import spl.token
20
+ import spl.token.constants
21
+ from spl.token.instructions import get_associated_token_address, create_associated_token_account,TransferCheckedParams, transfer_checked, transfer, close_account, TransferParams
22
+ from solders.system_program import transfer as ts
23
+ from solders.system_program import TransferParams as tsf
24
+ from solders.pubkey import Pubkey
25
+ import os
26
+ from spl.token.constants import TOKEN_PROGRAM_ID, ASSOCIATED_TOKEN_PROGRAM_ID
27
+ from solana.rpc.types import TxOpts, TokenAccountOpts
28
+ from solana.rpc.types import TxOpts
29
+ import solders
30
+ from solders.message import Message
31
+ from solders.system_program import create_account,CreateAccountParams
32
+
33
+ # from solders.pubkey import Pubkey
34
+ # from solders.keypair import Keypair
35
+ # from solders.signature import Signature
36
+ # from solders.transaction import Transaction
37
+ from spl.token.async_client import AsyncToken
38
+
39
+
40
+ from solana.rpc.commitment import Confirmed
41
+ from solana.rpc.async_api import AsyncClient
42
+ import anchorpy
43
+ from anchorpy import Provider, Wallet, Idl
44
+ import pprint
45
+ import httpx
46
+ import base64
47
+ import re
48
+ import struct
49
+ from shadowPaySDK.const import LAMPORTS_PER_SOL, PROGRAM_ID, CONFIG_PDA
9
50
 
10
51
 
11
52
 
12
53
  class SOLCheque:
13
- def __init__(self, rpc_url: str = "https://api.mainnet-beta.solana.com", keystore: Wallet = None):
54
+ def __init__(self, rpc_url: str = "https://api.mainnet-beta.solana.com", key: Wallet = None):
14
55
  self.rpc_url = rpc_url
15
- self.keystore = keystore
16
- self.provider = Provider(self.rpc_url, self.keystore)
56
+ if key:
57
+ self.key = solders.keypair.Keypair.from_base58_string(key)
58
+ self.provider = Client(rpc_url)
17
59
  self.WRAPED_SOL = spl_constants.WRAPPED_SOL_MINT # wrapped SOL token mint address
18
60
  # self.idl = Idl.from_json(sol_interface.Idl) # Load the IDL for the program
19
61
  def get(self, keypair = None):
20
- pubkey = SOL.get_pubkey(KEYPAIR=Keypair.from_base58_string(self.keystore))
62
+ pubkey = SOL.get_pubkey(KEYPAIR=solders.keypair.Keypair.from_base58_string(self.keystore))
21
63
 
22
64
  return pubkey
23
-
65
+ def get_config(self):
66
+ program_id = PROGRAM_ID
67
+ config_pda, _ = Pubkey.find_program_address([b"config"], program_id)
68
+
69
+ response = self.provider.get_account_info(config_pda)
70
+ if response.value is None:
71
+ print("❌ Config PDA not found.")
72
+ return None
73
+
74
+ # 🧠 У тебя data — это list[int], его нужно превратить в bytes
75
+ raw = bytes(response.value.data)
76
+
77
+ if len(raw) < 89:
78
+ print("❌ Invalid config data length.")
79
+ return None
80
+
81
+ admin = Pubkey.from_bytes(raw[0:32])
82
+ treasury = Pubkey.from_bytes(raw[32:64])
83
+ fee_bps = struct.unpack("<Q", raw[64:72])[0]
84
+ token_in_bps = struct.unpack("<Q", raw[72:80])[0]
85
+ token_out_bps = struct.unpack("<Q", raw[80:88])[0]
86
+ initialized = bool(raw[88])
87
+
88
+
89
+ return {
90
+ "pda": str(config_pda),
91
+ "admin": str(admin),
92
+ "treasury": str(treasury),
93
+ "fee_bps": fee_bps,
94
+ "token_in_bps": token_in_bps,
95
+ "token_out_bps": token_out_bps,
96
+ "initialized": initialized,
97
+ }
98
+ def set_params(self, rpc_url = None, key = None):
99
+ if rpc_url:
100
+ self.rpc_url = rpc_url
101
+ self.provider = Client(rpc_url)
102
+ if key:
103
+ self.key = solders.keypair.Keypair.from_base58_string(key)
104
+ # init_cheque & claim_cheque status on 15.07.2025 work
105
+
106
+ def init_cheque(self, cheque_amount, recipient: str, SPACE: int = 100, build_tx: bool = False):
107
+ """
108
+ Initialize a cheque withc the specified amount and recipient.
109
+ """
110
+ # if not self.key:
111
+ # raise ValueError("Keypair is not set. Please set the keypair before initializing a cheque.")
112
+ CHEQUE_PDA_SIGNATURE = None
113
+ CHEQUE_SPACE = SPACE
114
+ CHEQUE_RENT = self.provider.get_minimum_balance_for_rent_exemption(CHEQUE_SPACE)
115
+ sol = SOL(
116
+ KEYPAIR=self.key
117
+ )
118
+ payer = self.key
119
+ pubkey = self.key.pubkey()
120
+ newAcc = solders.keypair.Keypair()
121
+ newAccPubkey = newAcc.pubkey()
122
+ ix_create = create_account(
123
+ params=CreateAccountParams(
124
+ from_pubkey=pubkey,
125
+ to_pubkey=newAccPubkey,
126
+ lamports=CHEQUE_RENT.value,
127
+ space=CHEQUE_SPACE,
128
+ owner=PROGRAM_ID
129
+ )
130
+ )
131
+ recent_blockhash = self.provider.get_latest_blockhash().value.blockhash
132
+ message = Message(instructions=[ix_create], payer=pubkey)
133
+
134
+ t = Transaction(message=message, from_keypairs=[payer, newAcc], recent_blockhash=recent_blockhash)
135
+
136
+ r = self.provider.send_transaction(t,opts=TxOpts())
137
+ CHEQUE_PDA_SIGNATURE = r.value
138
+ CHEQUE_PDA = newAccPubkey
139
+
140
+
141
+
142
+ total_lamports = int(cheque_amount * LAMPORTS_PER_SOL)
143
+
144
+
145
+ r = Pubkey.from_string(recipient)
146
+
147
+ data = bytes([0]) + bytes(r) + struct.pack("<Q", total_lamports)
148
+
149
+ cfg = self.get_config()
150
+ tresury = cfg["treasury"]
151
+ instruction = Instruction(
152
+ program_id=PROGRAM_ID,
153
+ data=data,
154
+ accounts=[
155
+ AccountMeta(pubkey=pubkey, is_signer=True, is_writable=True), # payer
156
+ AccountMeta(pubkey=CHEQUE_PDA, is_signer=False, is_writable=True), # cheque PDA
157
+ AccountMeta(pubkey=Pubkey.from_string("11111111111111111111111111111111"), is_signer=False, is_writable=False),
158
+ AccountMeta(pubkey=Pubkey.from_string(tresury), is_signer=False, is_writable=True), # treasury
159
+
160
+ ]
161
+ )
162
+
163
+ recent_blockhash = self.provider.get_latest_blockhash().value.blockhash
164
+ message = Message(instructions=[instruction], payer=pubkey)
165
+ tx = Transaction(message=message, from_keypairs=[payer], recent_blockhash=recent_blockhash)
166
+ response = self.provider.send_transaction(tx,opts=TxOpts(skip_preflight=True))
167
+ confirm = self.provider.confirm_transaction(response.value)
168
+
169
+ data = {
170
+ "cheque_pda": str(CHEQUE_PDA),
171
+ "signature": str(response.value),
172
+ "create_signature": str(CHEQUE_PDA_SIGNATURE),
173
+ "cheque_amount": cheque_amount,
174
+ "pda_rent_sol": CHEQUE_RENT.value / LAMPORTS_PER_SOL,
175
+ }
176
+ return data
177
+
178
+ def claim_cheque(self, pda_acc: str ):
179
+ instruction_data = bytes([1])
180
+ payer = self.key
181
+ payer_pubkey = payer.pubkey()
182
+ cfg = self.get_config()
183
+ tressary = cfg["treasury"]
184
+
185
+
186
+ ix = Instruction(
187
+ program_id=PROGRAM_ID,
188
+ data=instruction_data,
189
+ accounts = [
190
+ AccountMeta(pubkey=payer_pubkey, is_signer=True, is_writable=True),
191
+ AccountMeta(pubkey=Pubkey.from_string(pda_acc), is_signer=False, is_writable=True),
192
+ AccountMeta(pubkey=CONFIG_PDA[0], is_signer=False, is_writable=True), # rent receiver
193
+ AccountMeta(pubkey=Pubkey.from_string(tressary), is_signer=False, is_writable=True) # treasury
194
+ ]
195
+ )
196
+
197
+ recent_blockhash = self.provider.get_latest_blockhash().value.blockhash
198
+ message = Message(instructions=[ix], payer=payer_pubkey)
199
+ tx = Transaction(message=message, from_keypairs=[payer], recent_blockhash=recent_blockhash)
200
+ response = self.provider.send_transaction(tx,opts=TxOpts(skip_preflight=True))
201
+ return {
202
+ "signature": str(response.value),
203
+ "pda_account": pda_acc,
204
+ }
205
+
206
+ # init_token_cheque need fix...
207
+
208
+ def init_token_cheque(self, token_mint: str, token_amount,token_decimals, recipient: str, treasury: str, CHEQUE_SPACE: int = 105):
209
+ if not self.key:
210
+ raise ValueError("Keypair not set")
211
+
212
+ payer = self.key
213
+ payer_pubkey = payer.pubkey()
214
+ token_mint_pubkey = Pubkey.from_string(token_mint)
215
+ recipient_pubkey = Pubkey.from_string(recipient)
216
+ treasury_pubkey = Pubkey.from_string(treasury)
217
+
218
+ cheque_acc = solders.keypair.Keypair()
219
+ cheque_pda = cheque_acc.pubkey()
220
+
221
+ rent = self.provider.get_minimum_balance_for_rent_exemption(CHEQUE_SPACE).value
222
+
223
+ create_cheque_acc = create_account(
224
+ CreateAccountParams(
225
+ from_pubkey=payer_pubkey,
226
+ to_pubkey=cheque_pda,
227
+ lamports=rent,
228
+ space=CHEQUE_SPACE,
229
+ owner=PROGRAM_ID
230
+ )
231
+ )
232
+
233
+ tx1 = Transaction(
234
+ message=Message(instructions=[create_cheque_acc], payer=payer_pubkey),
235
+ recent_blockhash=self.provider.get_latest_blockhash().value.blockhash,
236
+ from_keypairs=[payer, cheque_acc]
237
+ )
238
+ self.provider.send_transaction(tx1, opts=TxOpts(skip_preflight=True))
239
+
240
+ sender_ata = get_associated_token_address(payer_pubkey, token_mint_pubkey)
241
+ cheque_ata = get_associated_token_address(cheque_pda, token_mint_pubkey)
242
+ treasury_ata = get_associated_token_address(treasury_pubkey, token_mint_pubkey)
243
+
244
+ ix_create_ata = create_associated_token_account(payer_pubkey, cheque_pda, token_mint_pubkey)
245
+
246
+ amount = int(token_amount * (10 ** token_decimals))
247
+
248
+
249
+
250
+ data = bytes([2]) + struct.pack("<Q", amount)
251
+
252
+ ix_program = Instruction(
253
+ program_id=PROGRAM_ID,
254
+ data=data,
255
+ accounts=[
256
+ AccountMeta(payer_pubkey, is_signer=True, is_writable=True),
257
+ AccountMeta(cheque_pda, is_signer=True, is_writable=True),
258
+ AccountMeta(token_mint_pubkey, is_signer=False, is_writable=True),
259
+ AccountMeta(sender_ata, is_signer=False, is_writable=True),
260
+ AccountMeta(cheque_ata, is_signer=False, is_writable=True),
261
+ AccountMeta(treasury_ata, is_signer=False, is_writable=True),
262
+ AccountMeta(Pubkey.from_string("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"), is_signer=False, is_writable=False),
263
+ ]
264
+ )
24
265
 
266
+ # === 6. Собираем и отправляем всё в одном tx ===
267
+ print("Accounts (ix_program):")
268
+ for i, acc in enumerate(ix_program.accounts):
269
+ print(f"[{i}] {acc.pubkey} | signer={acc.is_signer} | writable={acc.is_writable}")
25
270
 
271
+ tx2 = Transaction(
272
+ message=Message(instructions=[ix_create_ata, ix_program], payer=payer_pubkey),
273
+ recent_blockhash=self.provider.get_latest_blockhash().value.blockhash,
274
+ from_keypairs=[payer, cheque_acc]
275
+ )
26
276
 
27
-
277
+ sig = self.provider.send_transaction(tx2, opts=TxOpts(skip_preflight=True)).value
278
+ return {
279
+ "cheque_pda": str(cheque_pda),
280
+ "signature": str(sig),
281
+ "amount": token_amount
282
+ }
283
+ def claim_token_cheque(self, pda_acc: str):
284
+ pass
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: shadowPaySDK
3
- Version: 0.2.1
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>=6.0.0
15
- Requires-Dist: requests>=2.28.0
16
- Requires-Dist: solana==0.36.7
17
- Requires-Dist: anchorpy>=0.21.0
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
- # shadowPayS
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,17 @@
1
+ shadowPaySDK/__init__.py,sha256=CMwAuP_6hJN-WueU-XlTNta9Oyd28sFo8OojdgD_pxA,681
2
+ shadowPaySDK/api.py,sha256=cv5Z171cOh-Idi-lMA4AORzeGDPPrk8BCQ9e5V9MAaM,1461
3
+ shadowPaySDK/const.py,sha256=dIifSDi2SEW7W3e-Z1nG3TwpAqPNnXvnFipGP0cgPwE,10318
4
+ shadowPaySDK/interface/__init__.py,sha256=ggSZCV22udnzXm_Wv_3x6VN3hNIAEiwgwHZc2Jwc688,146
5
+ shadowPaySDK/interface/erc20.py,sha256=7p8eU5LzhI2MsH80PZhq6IRhbfMGlNYucGl3OtyS9SI,4669
6
+ shadowPaySDK/interface/erc721.py,sha256=4AlWfDjrvl85wFocnN93j-oM54kTsLLwv9SdtcLj4eM,3094
7
+ shadowPaySDK/interface/sol.py,sha256=TDp62OtQkR8Wy9I4UBVmL_K_FQeMVS--Lojgbvq5T2E,8146
8
+ shadowPaySDK/types/EVMcheque.py,sha256=8M1EzpZGqf4uidrd9yDKiR7BvIl85p93A_9AMZtshSs,14570
9
+ shadowPaySDK/types/SOLcheque.py,sha256=h1u-VaIhdb5hFWScdePCQDeDhIyyFhKgtZWmZ8vckh4,11991
10
+ shadowPaySDK/types/__init__.py,sha256=sG6pNZfKGvENXqsnv6MrQtKrJ898fAXkMvAZY1k1-Qg,97
11
+ shadowPaySDK/utils/__init__.py,sha256=aja3iYO4rT-ptMM-pzw0GRFTziBdXdcEi-4kE84zH64,61
12
+ shadowPaySDK/utils/utils.py,sha256=g4bGvLDdjhNGsAj1eaZnNWFNaiN-cVhhM-5PrnG5aIQ,720
13
+ shadowpaysdk-16.7.2025.1.dist-info/licenses/LICENSE,sha256=EG13vNmyBfkG3oKj40oOYfUGLKko8OouU6PfO6MlAk4,1066
14
+ shadowpaysdk-16.7.2025.1.dist-info/METADATA,sha256=Df0LLF--lTt4X9nDkbor0opwMawm-9LeaFSZOrqZnWE,1046
15
+ shadowpaysdk-16.7.2025.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
16
+ shadowpaysdk-16.7.2025.1.dist-info/top_level.txt,sha256=RSJc73GEf31NMdZp9KovEduzfhm10eQ2t5GTZ44aN1U,13
17
+ shadowpaysdk-16.7.2025.1.dist-info/RECORD,,
@@ -1,17 +0,0 @@
1
- shadowPaySDK/__init__.py,sha256=f3O3u7UX-WTEuy1DPS6vQ8w672nzR1ZbVMu8hciqxM8,821
2
- shadowPaySDK/api.py,sha256=cv5Z171cOh-Idi-lMA4AORzeGDPPrk8BCQ9e5V9MAaM,1461
3
- shadowPaySDK/const.py,sha256=WC560zlT9MlG9QKlJb8Ww6ITfL4xR6vRH4kcGzVHFRI,9893
4
- shadowPaySDK/interface/__init__.py,sha256=QceU3dWteSgwvMnR3JDVdmS8OgdRPjvl9JzRs7IsA74,152
5
- shadowPaySDK/interface/erc20.py,sha256=rsdfjIrPNxC_xHbUT9FQbNhURdIqZHcylxTbskPHu1k,4453
6
- shadowPaySDK/interface/erc721.py,sha256=4AlWfDjrvl85wFocnN93j-oM54kTsLLwv9SdtcLj4eM,3094
7
- shadowPaySDK/interface/sol.py,sha256=xgJZsg4xE-_dRctGUW_mHuGj_o_0OlKNp4Gr7IXvTEc,5586
8
- shadowPaySDK/types/EVMcheque.py,sha256=lmPvHlt-ERkaYx2DTYwGmbF_TI1B_ZTT3G_FIQPBm_o,12466
9
- shadowPaySDK/types/SOLcheque.py,sha256=gmivsCK4hm_6pzQ9whPGuQ_f7qfcUfiJfQgb5ZsJYDo,884
10
- shadowPaySDK/types/__init__.py,sha256=sG6pNZfKGvENXqsnv6MrQtKrJ898fAXkMvAZY1k1-Qg,97
11
- shadowPaySDK/utils/__init__.py,sha256=aja3iYO4rT-ptMM-pzw0GRFTziBdXdcEi-4kE84zH64,61
12
- shadowPaySDK/utils/utils.py,sha256=g4bGvLDdjhNGsAj1eaZnNWFNaiN-cVhhM-5PrnG5aIQ,720
13
- shadowpaysdk-0.2.1.dist-info/licenses/LICENSE,sha256=EG13vNmyBfkG3oKj40oOYfUGLKko8OouU6PfO6MlAk4,1066
14
- shadowpaysdk-0.2.1.dist-info/METADATA,sha256=oVHKTeuCSJ64v1EKXBhslX7U97X2VP68Cdgpn9LWwCw,868
15
- shadowpaysdk-0.2.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
16
- shadowpaysdk-0.2.1.dist-info/top_level.txt,sha256=RSJc73GEf31NMdZp9KovEduzfhm10eQ2t5GTZ44aN1U,13
17
- shadowpaysdk-0.2.1.dist-info/RECORD,,