t402 1.9.1__py3-none-any.whl → 1.10.0__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.
- t402/__init__.py +1 -1
- t402/a2a/__init__.py +73 -0
- t402/a2a/helpers.py +158 -0
- t402/a2a/types.py +145 -0
- t402/bridge/constants.py +1 -1
- t402/django/__init__.py +42 -0
- t402/django/middleware.py +596 -0
- t402/errors.py +213 -0
- t402/facilitator.py +125 -0
- t402/mcp/constants.py +3 -6
- t402/mcp/server.py +428 -44
- t402/mcp/web3_utils.py +493 -0
- t402/multisig/__init__.py +120 -0
- t402/multisig/constants.py +54 -0
- t402/multisig/safe.py +441 -0
- t402/multisig/signature.py +228 -0
- t402/multisig/transaction.py +238 -0
- t402/multisig/types.py +108 -0
- t402/multisig/utils.py +77 -0
- t402/schemes/__init__.py +19 -0
- t402/schemes/cosmos/__init__.py +114 -0
- t402/schemes/cosmos/constants.py +211 -0
- t402/schemes/cosmos/exact_direct/__init__.py +21 -0
- t402/schemes/cosmos/exact_direct/client.py +198 -0
- t402/schemes/cosmos/exact_direct/facilitator.py +493 -0
- t402/schemes/cosmos/exact_direct/server.py +315 -0
- t402/schemes/cosmos/types.py +501 -0
- t402/schemes/evm/__init__.py +1 -1
- t402/schemes/evm/exact_legacy/server.py +1 -1
- t402/schemes/near/__init__.py +25 -0
- t402/schemes/near/upto/__init__.py +54 -0
- t402/schemes/near/upto/types.py +272 -0
- t402/schemes/svm/__init__.py +15 -0
- t402/schemes/svm/upto/__init__.py +23 -0
- t402/schemes/svm/upto/types.py +193 -0
- t402/schemes/ton/__init__.py +15 -0
- t402/schemes/ton/upto/__init__.py +31 -0
- t402/schemes/ton/upto/types.py +215 -0
- t402/schemes/tron/__init__.py +21 -4
- t402/schemes/tron/upto/__init__.py +30 -0
- t402/schemes/tron/upto/types.py +213 -0
- t402/starlette/__init__.py +38 -0
- t402/starlette/middleware.py +522 -0
- t402/ton.py +1 -1
- t402/ton_paywall_template.py +1 -1
- t402/types.py +100 -2
- t402/wdk/chains.py +1 -1
- {t402-1.9.1.dist-info → t402-1.10.0.dist-info}/METADATA +3 -3
- {t402-1.9.1.dist-info → t402-1.10.0.dist-info}/RECORD +51 -20
- {t402-1.9.1.dist-info → t402-1.10.0.dist-info}/WHEEL +0 -0
- {t402-1.9.1.dist-info → t402-1.10.0.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Transaction builder for T402 Multi-sig (Safe) support.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import List, Optional
|
|
6
|
+
|
|
7
|
+
from web3 import Web3
|
|
8
|
+
|
|
9
|
+
from .constants import SAFE_MULTISEND, ERC20_TRANSFER_SELECTOR, MULTISEND_SELECTOR
|
|
10
|
+
from .types import SafeTransaction, OperationType
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TransactionBuilder:
|
|
14
|
+
"""Builder for Safe transactions."""
|
|
15
|
+
|
|
16
|
+
def __init__(self):
|
|
17
|
+
"""Initialize TransactionBuilder."""
|
|
18
|
+
self._to: str = "0x0000000000000000000000000000000000000000"
|
|
19
|
+
self._value: int = 0
|
|
20
|
+
self._data: bytes = b""
|
|
21
|
+
self._operation: OperationType = OperationType.CALL
|
|
22
|
+
self._safe_tx_gas: int = 0
|
|
23
|
+
self._base_gas: int = 0
|
|
24
|
+
self._gas_price: int = 0
|
|
25
|
+
self._gas_token: str = "0x0000000000000000000000000000000000000000"
|
|
26
|
+
self._refund_receiver: str = "0x0000000000000000000000000000000000000000"
|
|
27
|
+
self._nonce: Optional[int] = None
|
|
28
|
+
|
|
29
|
+
def to(self, address: str) -> "TransactionBuilder":
|
|
30
|
+
"""Set the target address."""
|
|
31
|
+
self._to = Web3.to_checksum_address(address)
|
|
32
|
+
return self
|
|
33
|
+
|
|
34
|
+
def value(self, amount: int) -> "TransactionBuilder":
|
|
35
|
+
"""Set the ETH value to send."""
|
|
36
|
+
self._value = amount
|
|
37
|
+
return self
|
|
38
|
+
|
|
39
|
+
def data(self, data: bytes) -> "TransactionBuilder":
|
|
40
|
+
"""Set the calldata."""
|
|
41
|
+
self._data = data
|
|
42
|
+
return self
|
|
43
|
+
|
|
44
|
+
def operation(self, op: OperationType) -> "TransactionBuilder":
|
|
45
|
+
"""Set the operation type."""
|
|
46
|
+
self._operation = op
|
|
47
|
+
return self
|
|
48
|
+
|
|
49
|
+
def delegate_call(self) -> "TransactionBuilder":
|
|
50
|
+
"""Set operation to delegate call."""
|
|
51
|
+
self._operation = OperationType.DELEGATE_CALL
|
|
52
|
+
return self
|
|
53
|
+
|
|
54
|
+
def safe_tx_gas(self, gas: int) -> "TransactionBuilder":
|
|
55
|
+
"""Set the Safe transaction gas."""
|
|
56
|
+
self._safe_tx_gas = gas
|
|
57
|
+
return self
|
|
58
|
+
|
|
59
|
+
def base_gas(self, gas: int) -> "TransactionBuilder":
|
|
60
|
+
"""Set the base gas."""
|
|
61
|
+
self._base_gas = gas
|
|
62
|
+
return self
|
|
63
|
+
|
|
64
|
+
def gas_price(self, price: int) -> "TransactionBuilder":
|
|
65
|
+
"""Set the gas price for refund."""
|
|
66
|
+
self._gas_price = price
|
|
67
|
+
return self
|
|
68
|
+
|
|
69
|
+
def gas_token(self, token: str) -> "TransactionBuilder":
|
|
70
|
+
"""Set the token for gas refund (zero address for ETH)."""
|
|
71
|
+
self._gas_token = Web3.to_checksum_address(token)
|
|
72
|
+
return self
|
|
73
|
+
|
|
74
|
+
def refund_receiver(self, receiver: str) -> "TransactionBuilder":
|
|
75
|
+
"""Set the address to receive gas refund."""
|
|
76
|
+
self._refund_receiver = Web3.to_checksum_address(receiver)
|
|
77
|
+
return self
|
|
78
|
+
|
|
79
|
+
def nonce(self, nonce: int) -> "TransactionBuilder":
|
|
80
|
+
"""Set the Safe nonce."""
|
|
81
|
+
self._nonce = nonce
|
|
82
|
+
return self
|
|
83
|
+
|
|
84
|
+
def build(self) -> SafeTransaction:
|
|
85
|
+
"""Build the SafeTransaction."""
|
|
86
|
+
return SafeTransaction(
|
|
87
|
+
to=self._to,
|
|
88
|
+
value=self._value,
|
|
89
|
+
data=self._data,
|
|
90
|
+
operation=self._operation,
|
|
91
|
+
safe_tx_gas=self._safe_tx_gas,
|
|
92
|
+
base_gas=self._base_gas,
|
|
93
|
+
gas_price=self._gas_price,
|
|
94
|
+
gas_token=self._gas_token,
|
|
95
|
+
refund_receiver=self._refund_receiver,
|
|
96
|
+
nonce=self._nonce,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def erc20_transfer(token: str, to: str, amount: int) -> SafeTransaction:
|
|
101
|
+
"""
|
|
102
|
+
Create a transaction for ERC20 token transfer.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
token: Token contract address.
|
|
106
|
+
to: Recipient address.
|
|
107
|
+
amount: Amount in smallest units.
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
SafeTransaction for the transfer.
|
|
111
|
+
"""
|
|
112
|
+
# Build calldata: transfer(address,uint256)
|
|
113
|
+
to_addr = Web3.to_checksum_address(to)
|
|
114
|
+
data = (
|
|
115
|
+
ERC20_TRANSFER_SELECTOR
|
|
116
|
+
+ bytes(12) # Padding for address
|
|
117
|
+
+ bytes.fromhex(to_addr[2:])
|
|
118
|
+
+ amount.to_bytes(32, "big")
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
return (
|
|
122
|
+
TransactionBuilder()
|
|
123
|
+
.to(token)
|
|
124
|
+
.data(data)
|
|
125
|
+
.build()
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def eth_transfer(to: str, amount: int) -> SafeTransaction:
|
|
130
|
+
"""
|
|
131
|
+
Create a transaction for sending ETH.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
to: Recipient address.
|
|
135
|
+
amount: Amount in wei.
|
|
136
|
+
|
|
137
|
+
Returns:
|
|
138
|
+
SafeTransaction for the transfer.
|
|
139
|
+
"""
|
|
140
|
+
return (
|
|
141
|
+
TransactionBuilder()
|
|
142
|
+
.to(to)
|
|
143
|
+
.value(amount)
|
|
144
|
+
.build()
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def contract_call(target: str, data: bytes) -> SafeTransaction:
|
|
149
|
+
"""
|
|
150
|
+
Create a transaction for calling a contract.
|
|
151
|
+
|
|
152
|
+
Args:
|
|
153
|
+
target: Target contract address.
|
|
154
|
+
data: Calldata.
|
|
155
|
+
|
|
156
|
+
Returns:
|
|
157
|
+
SafeTransaction for the call.
|
|
158
|
+
"""
|
|
159
|
+
return (
|
|
160
|
+
TransactionBuilder()
|
|
161
|
+
.to(target)
|
|
162
|
+
.data(data)
|
|
163
|
+
.build()
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
class BatchTransactionBuilder:
|
|
168
|
+
"""Builder for batch transactions via MultiSend."""
|
|
169
|
+
|
|
170
|
+
def __init__(self):
|
|
171
|
+
"""Initialize BatchTransactionBuilder."""
|
|
172
|
+
self._transactions: List[SafeTransaction] = []
|
|
173
|
+
|
|
174
|
+
def add(self, tx: SafeTransaction) -> "BatchTransactionBuilder":
|
|
175
|
+
"""Add a transaction to the batch."""
|
|
176
|
+
self._transactions.append(tx)
|
|
177
|
+
return self
|
|
178
|
+
|
|
179
|
+
def add_transfer(
|
|
180
|
+
self, token: str, to: str, amount: int
|
|
181
|
+
) -> "BatchTransactionBuilder":
|
|
182
|
+
"""Add an ERC20 transfer to the batch."""
|
|
183
|
+
return self.add(erc20_transfer(token, to, amount))
|
|
184
|
+
|
|
185
|
+
def add_eth_transfer(self, to: str, amount: int) -> "BatchTransactionBuilder":
|
|
186
|
+
"""Add an ETH transfer to the batch."""
|
|
187
|
+
return self.add(eth_transfer(to, amount))
|
|
188
|
+
|
|
189
|
+
def build(self) -> List[SafeTransaction]:
|
|
190
|
+
"""Return all transactions in the batch."""
|
|
191
|
+
return self._transactions.copy()
|
|
192
|
+
|
|
193
|
+
def build_multisend(self) -> SafeTransaction:
|
|
194
|
+
"""
|
|
195
|
+
Create a single transaction that executes all batch transactions via MultiSend.
|
|
196
|
+
|
|
197
|
+
Returns:
|
|
198
|
+
SafeTransaction for MultiSend execution.
|
|
199
|
+
"""
|
|
200
|
+
# Encode each transaction for MultiSend
|
|
201
|
+
# Format: operation (1 byte) + to (20 bytes) + value (32 bytes) +
|
|
202
|
+
# dataLength (32 bytes) + data (variable)
|
|
203
|
+
packed_txs = b""
|
|
204
|
+
for tx in self._transactions:
|
|
205
|
+
# Operation (1 byte)
|
|
206
|
+
packed_txs += bytes([tx.operation])
|
|
207
|
+
|
|
208
|
+
# To (20 bytes)
|
|
209
|
+
packed_txs += bytes.fromhex(tx.to[2:])
|
|
210
|
+
|
|
211
|
+
# Value (32 bytes)
|
|
212
|
+
packed_txs += tx.value.to_bytes(32, "big")
|
|
213
|
+
|
|
214
|
+
# Data length (32 bytes)
|
|
215
|
+
packed_txs += len(tx.data).to_bytes(32, "big")
|
|
216
|
+
|
|
217
|
+
# Data
|
|
218
|
+
packed_txs += tx.data
|
|
219
|
+
|
|
220
|
+
# Build MultiSend calldata
|
|
221
|
+
# multiSend(bytes transactions)
|
|
222
|
+
# Offset (32 bytes) + Length (32 bytes) + Data (padded to 32 bytes)
|
|
223
|
+
offset = (32).to_bytes(32, "big") # Offset to data
|
|
224
|
+
length = len(packed_txs).to_bytes(32, "big")
|
|
225
|
+
|
|
226
|
+
# Pad to 32-byte boundary
|
|
227
|
+
padded_len = ((len(packed_txs) + 31) // 32) * 32
|
|
228
|
+
padded_data = packed_txs + b"\x00" * (padded_len - len(packed_txs))
|
|
229
|
+
|
|
230
|
+
calldata = MULTISEND_SELECTOR + offset + length + padded_data
|
|
231
|
+
|
|
232
|
+
return (
|
|
233
|
+
TransactionBuilder()
|
|
234
|
+
.to(SAFE_MULTISEND)
|
|
235
|
+
.data(calldata)
|
|
236
|
+
.delegate_call()
|
|
237
|
+
.build()
|
|
238
|
+
)
|
t402/multisig/types.py
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Type definitions for T402 Multi-sig (Safe) support.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from enum import IntEnum
|
|
7
|
+
from typing import Dict, List, Optional
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class SignatureType(IntEnum):
|
|
11
|
+
"""Type of signature for Safe transactions."""
|
|
12
|
+
|
|
13
|
+
EOA = 0 # Standard EOA signature
|
|
14
|
+
CONTRACT = 1 # EIP-1271 contract signature
|
|
15
|
+
APPROVED_HASH = 4 # Pre-approved hash
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class OperationType(IntEnum):
|
|
19
|
+
"""Operation type for Safe transactions."""
|
|
20
|
+
|
|
21
|
+
CALL = 0
|
|
22
|
+
DELEGATE_CALL = 1
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass
|
|
26
|
+
class SafeConfig:
|
|
27
|
+
"""Configuration for a Safe multi-sig account."""
|
|
28
|
+
|
|
29
|
+
address: str
|
|
30
|
+
rpc_url: str
|
|
31
|
+
chain_id: Optional[int] = None
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@dataclass
|
|
35
|
+
class SafeOwner:
|
|
36
|
+
"""Represents an owner of a Safe account."""
|
|
37
|
+
|
|
38
|
+
address: str
|
|
39
|
+
index: int
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@dataclass
|
|
43
|
+
class SafeTransaction:
|
|
44
|
+
"""Represents a pending Safe transaction."""
|
|
45
|
+
|
|
46
|
+
to: str
|
|
47
|
+
value: int = 0
|
|
48
|
+
data: bytes = field(default_factory=bytes)
|
|
49
|
+
operation: OperationType = OperationType.CALL
|
|
50
|
+
safe_tx_gas: int = 0
|
|
51
|
+
base_gas: int = 0
|
|
52
|
+
gas_price: int = 0
|
|
53
|
+
gas_token: str = "0x0000000000000000000000000000000000000000"
|
|
54
|
+
refund_receiver: str = "0x0000000000000000000000000000000000000000"
|
|
55
|
+
nonce: Optional[int] = None
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@dataclass
|
|
59
|
+
class SafeSignature:
|
|
60
|
+
"""Holds a signature from a Safe owner."""
|
|
61
|
+
|
|
62
|
+
signer: str
|
|
63
|
+
signature: bytes
|
|
64
|
+
signature_type: SignatureType = SignatureType.EOA
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@dataclass
|
|
68
|
+
class TransactionRequest:
|
|
69
|
+
"""Represents a multi-sig transaction awaiting signatures."""
|
|
70
|
+
|
|
71
|
+
id: str
|
|
72
|
+
safe_address: str
|
|
73
|
+
transaction: SafeTransaction
|
|
74
|
+
transaction_hash: str
|
|
75
|
+
signatures: Dict[str, SafeSignature] = field(default_factory=dict)
|
|
76
|
+
threshold: int = 0
|
|
77
|
+
created_at: int = 0
|
|
78
|
+
expires_at: int = 0
|
|
79
|
+
|
|
80
|
+
def is_ready(self) -> bool:
|
|
81
|
+
"""Check if enough signatures have been collected."""
|
|
82
|
+
return len(self.signatures) >= self.threshold
|
|
83
|
+
|
|
84
|
+
def collected_count(self) -> int:
|
|
85
|
+
"""Return the number of signatures collected."""
|
|
86
|
+
return len(self.signatures)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@dataclass
|
|
90
|
+
class SafeInfo:
|
|
91
|
+
"""Information about a Safe account."""
|
|
92
|
+
|
|
93
|
+
address: str
|
|
94
|
+
owners: List[str]
|
|
95
|
+
threshold: int
|
|
96
|
+
nonce: int
|
|
97
|
+
version: Optional[str] = None
|
|
98
|
+
chain_id: Optional[int] = None
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
@dataclass
|
|
102
|
+
class ExecutionResult:
|
|
103
|
+
"""Result of executing a Safe transaction."""
|
|
104
|
+
|
|
105
|
+
tx_hash: str
|
|
106
|
+
success: bool
|
|
107
|
+
gas_used: int = 0
|
|
108
|
+
block_number: int = 0
|
t402/multisig/utils.py
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Utility functions for T402 Multi-sig support.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import secrets
|
|
6
|
+
import time
|
|
7
|
+
from typing import List
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def generate_request_id() -> str:
|
|
11
|
+
"""Generate a unique request ID."""
|
|
12
|
+
timestamp = int(time.time() * 1000)
|
|
13
|
+
random_bytes = secrets.token_hex(4)
|
|
14
|
+
return f"msig_{timestamp:x}_{random_bytes}"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def current_timestamp() -> int:
|
|
18
|
+
"""Get current Unix timestamp in seconds."""
|
|
19
|
+
return int(time.time())
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def sort_addresses(addresses: List[str]) -> List[str]:
|
|
23
|
+
"""Sort addresses in ascending order (case-insensitive)."""
|
|
24
|
+
return sorted(addresses, key=lambda a: a.lower())
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def is_valid_threshold(threshold: int, owner_count: int) -> bool:
|
|
28
|
+
"""Check if a threshold is valid for the given owner count."""
|
|
29
|
+
from .constants import MIN_THRESHOLD
|
|
30
|
+
|
|
31
|
+
return MIN_THRESHOLD <= threshold <= owner_count
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def are_addresses_unique(addresses: List[str]) -> bool:
|
|
35
|
+
"""Check if all addresses are unique (case-insensitive)."""
|
|
36
|
+
lower_addresses = [a.lower() for a in addresses]
|
|
37
|
+
return len(set(lower_addresses)) == len(addresses)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def get_owner_index(owner: str, owners: List[str]) -> int:
|
|
41
|
+
"""
|
|
42
|
+
Get the index of an owner in the list.
|
|
43
|
+
|
|
44
|
+
Returns -1 if not found.
|
|
45
|
+
"""
|
|
46
|
+
owner_lower = owner.lower()
|
|
47
|
+
for i, o in enumerate(owners):
|
|
48
|
+
if o.lower() == owner_lower:
|
|
49
|
+
return i
|
|
50
|
+
return -1
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def combine_signatures(signatures: dict) -> bytes:
|
|
54
|
+
"""
|
|
55
|
+
Combine multiple signatures sorted by signer address.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
signatures: Dict mapping signer address to SafeSignature.
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
Combined signature bytes.
|
|
62
|
+
"""
|
|
63
|
+
sorted_signers = sort_addresses(list(signatures.keys()))
|
|
64
|
+
|
|
65
|
+
packed = b""
|
|
66
|
+
for signer in sorted_signers:
|
|
67
|
+
sig = signatures[signer.lower()]
|
|
68
|
+
packed += sig.signature
|
|
69
|
+
|
|
70
|
+
return packed
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def pad_to_32_bytes(data: bytes) -> bytes:
|
|
74
|
+
"""Pad data to 32 bytes."""
|
|
75
|
+
if len(data) >= 32:
|
|
76
|
+
return data[-32:]
|
|
77
|
+
return b"\x00" * (32 - len(data)) + data
|
t402/schemes/__init__.py
CHANGED
|
@@ -179,6 +179,17 @@ from t402.schemes.stacks import (
|
|
|
179
179
|
SCHEME_EXACT_DIRECT as STACKS_SCHEME_EXACT_DIRECT,
|
|
180
180
|
)
|
|
181
181
|
|
|
182
|
+
# Cosmos Schemes
|
|
183
|
+
from t402.schemes.cosmos import (
|
|
184
|
+
ExactDirectCosmosClientScheme,
|
|
185
|
+
ExactDirectCosmosServerScheme,
|
|
186
|
+
ExactDirectCosmosFacilitatorScheme,
|
|
187
|
+
ExactDirectCosmosFacilitatorConfig,
|
|
188
|
+
ClientCosmosSigner,
|
|
189
|
+
FacilitatorCosmosSigner,
|
|
190
|
+
SCHEME_EXACT_DIRECT as COSMOS_SCHEME_EXACT_DIRECT,
|
|
191
|
+
)
|
|
192
|
+
|
|
182
193
|
__all__ = [
|
|
183
194
|
# Type aliases
|
|
184
195
|
"Price",
|
|
@@ -285,4 +296,12 @@ __all__ = [
|
|
|
285
296
|
"ClientStacksSigner",
|
|
286
297
|
"FacilitatorStacksSigner",
|
|
287
298
|
"STACKS_SCHEME_EXACT_DIRECT",
|
|
299
|
+
# Cosmos Schemes
|
|
300
|
+
"ExactDirectCosmosClientScheme",
|
|
301
|
+
"ExactDirectCosmosServerScheme",
|
|
302
|
+
"ExactDirectCosmosFacilitatorScheme",
|
|
303
|
+
"ExactDirectCosmosFacilitatorConfig",
|
|
304
|
+
"ClientCosmosSigner",
|
|
305
|
+
"FacilitatorCosmosSigner",
|
|
306
|
+
"COSMOS_SCHEME_EXACT_DIRECT",
|
|
288
307
|
]
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"""Cosmos/Noble Blockchain Payment Schemes.
|
|
2
|
+
|
|
3
|
+
This package provides payment scheme implementations for the Cosmos/Noble blockchain.
|
|
4
|
+
|
|
5
|
+
Supported schemes:
|
|
6
|
+
- exact-direct: Client executes bank MsgSend, tx hash used as proof.
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
```python
|
|
10
|
+
from t402.schemes.cosmos import (
|
|
11
|
+
# Client
|
|
12
|
+
ExactDirectCosmosClientScheme,
|
|
13
|
+
ExactDirectCosmosClientConfig,
|
|
14
|
+
# Server
|
|
15
|
+
ExactDirectCosmosServerScheme,
|
|
16
|
+
ExactDirectCosmosServerConfig,
|
|
17
|
+
# Facilitator
|
|
18
|
+
ExactDirectCosmosFacilitatorScheme,
|
|
19
|
+
ExactDirectCosmosFacilitatorConfig,
|
|
20
|
+
# Signer protocols
|
|
21
|
+
ClientCosmosSigner,
|
|
22
|
+
FacilitatorCosmosSigner,
|
|
23
|
+
# Constants
|
|
24
|
+
SCHEME_EXACT_DIRECT,
|
|
25
|
+
COSMOS_NOBLE_MAINNET,
|
|
26
|
+
COSMOS_NOBLE_TESTNET,
|
|
27
|
+
)
|
|
28
|
+
```
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
from t402.schemes.cosmos.exact_direct import (
|
|
32
|
+
ExactDirectCosmosClientScheme,
|
|
33
|
+
ExactDirectCosmosServerScheme,
|
|
34
|
+
ExactDirectCosmosFacilitatorScheme,
|
|
35
|
+
)
|
|
36
|
+
from t402.schemes.cosmos.exact_direct.client import ExactDirectCosmosClientConfig
|
|
37
|
+
from t402.schemes.cosmos.exact_direct.server import ExactDirectCosmosServerConfig
|
|
38
|
+
from t402.schemes.cosmos.exact_direct.facilitator import ExactDirectCosmosFacilitatorConfig
|
|
39
|
+
from t402.schemes.cosmos.types import (
|
|
40
|
+
ClientCosmosSigner,
|
|
41
|
+
FacilitatorCosmosSigner,
|
|
42
|
+
ExactDirectPayload,
|
|
43
|
+
TransactionResult,
|
|
44
|
+
MsgSend,
|
|
45
|
+
Coin,
|
|
46
|
+
)
|
|
47
|
+
from t402.schemes.cosmos.constants import (
|
|
48
|
+
SCHEME_EXACT_DIRECT,
|
|
49
|
+
COSMOS_NOBLE_MAINNET,
|
|
50
|
+
COSMOS_NOBLE_TESTNET,
|
|
51
|
+
NOBLE_MAINNET_RPC,
|
|
52
|
+
NOBLE_TESTNET_RPC,
|
|
53
|
+
NOBLE_MAINNET_REST,
|
|
54
|
+
NOBLE_TESTNET_REST,
|
|
55
|
+
NOBLE_BECH32_PREFIX,
|
|
56
|
+
USDC_DENOM,
|
|
57
|
+
DEFAULT_GAS_LIMIT,
|
|
58
|
+
MSG_TYPE_SEND,
|
|
59
|
+
CAIP_FAMILY,
|
|
60
|
+
USDC_TOKEN,
|
|
61
|
+
TokenInfo,
|
|
62
|
+
NetworkConfig,
|
|
63
|
+
get_network_config,
|
|
64
|
+
get_token_info,
|
|
65
|
+
get_token_by_denom,
|
|
66
|
+
is_valid_network,
|
|
67
|
+
is_valid_address,
|
|
68
|
+
get_supported_networks,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
__all__ = [
|
|
72
|
+
# Scheme implementations
|
|
73
|
+
"ExactDirectCosmosClientScheme",
|
|
74
|
+
"ExactDirectCosmosServerScheme",
|
|
75
|
+
"ExactDirectCosmosFacilitatorScheme",
|
|
76
|
+
# Configurations
|
|
77
|
+
"ExactDirectCosmosClientConfig",
|
|
78
|
+
"ExactDirectCosmosServerConfig",
|
|
79
|
+
"ExactDirectCosmosFacilitatorConfig",
|
|
80
|
+
# Signer protocols
|
|
81
|
+
"ClientCosmosSigner",
|
|
82
|
+
"FacilitatorCosmosSigner",
|
|
83
|
+
# Payload types
|
|
84
|
+
"ExactDirectPayload",
|
|
85
|
+
"TransactionResult",
|
|
86
|
+
"MsgSend",
|
|
87
|
+
"Coin",
|
|
88
|
+
# Validation
|
|
89
|
+
"is_valid_network",
|
|
90
|
+
"is_valid_address",
|
|
91
|
+
# Constants
|
|
92
|
+
"SCHEME_EXACT_DIRECT",
|
|
93
|
+
"COSMOS_NOBLE_MAINNET",
|
|
94
|
+
"COSMOS_NOBLE_TESTNET",
|
|
95
|
+
"NOBLE_MAINNET_RPC",
|
|
96
|
+
"NOBLE_TESTNET_RPC",
|
|
97
|
+
"NOBLE_MAINNET_REST",
|
|
98
|
+
"NOBLE_TESTNET_REST",
|
|
99
|
+
"NOBLE_BECH32_PREFIX",
|
|
100
|
+
"USDC_DENOM",
|
|
101
|
+
"DEFAULT_GAS_LIMIT",
|
|
102
|
+
"MSG_TYPE_SEND",
|
|
103
|
+
"CAIP_FAMILY",
|
|
104
|
+
# Token definitions
|
|
105
|
+
"USDC_TOKEN",
|
|
106
|
+
# Data classes
|
|
107
|
+
"TokenInfo",
|
|
108
|
+
"NetworkConfig",
|
|
109
|
+
# Lookup functions
|
|
110
|
+
"get_network_config",
|
|
111
|
+
"get_token_info",
|
|
112
|
+
"get_token_by_denom",
|
|
113
|
+
"get_supported_networks",
|
|
114
|
+
]
|