class DeployIdentity(Resource): def __init__(self, trustlines: TrustlinesRelay) -> None: self.trustlines = trustlines args = { "factoryAddress": custom_fields.Address(required=True), "implementationAddress": custom_fields.Address(required=True), "signature": custom_fields.HexEncodedBytes(required=True), } @use_args(args) @dump_result_with_schema(IdentityInfosSchema()) def post(self, args): implementation_address = args["implementationAddress"] factory_address = args["factoryAddress"] signature = args["signature"] try: identity_contract_address = self.trustlines.deploy_identity( factory_address, implementation_address, signature) except UnknownIdentityFactoryException as exception: abort( 400, f"The identity deployment was rejected, unknown factory: {exception.args}", ) except IdentityDeploymentFailedException: abort( 400, "The identity deployment failed, identity already deployed?") return self.trustlines.get_identity_info(identity_contract_address)
class CloseTrustline(Resource): def __init__(self, trustlines: TrustlinesRelay) -> None: self.trustlines = trustlines args = { "maxHops": fields.Int(required=False, missing=None), "maxFees": fields.Int(required=False, missing=None), "from": custom_fields.Address(required=True), "to": custom_fields.Address(required=True), } @use_args(args) @dump_result_with_schema(PaymentPathSchema()) def post(self, args, network_address: str): abort_if_unknown_or_frozen_network(self.trustlines, network_address) source = args["from"] target = args["to"] max_fees = args["maxFees"] max_hops = args["maxHops"] now = int(time.time()) graph = self.trustlines.currency_network_graphs[network_address] payment_path = graph.close_trustline_path_triangulation( timestamp=now, source=source, target=target, max_hops=max_hops, max_fees=max_fees, ) return payment_path
class MaxCapacityPath(Resource): def __init__(self, trustlines: TrustlinesRelay) -> None: self.trustlines = trustlines args = { "maxHops": fields.Int(required=False, missing=None), "from": custom_fields.Address(required=True), "to": custom_fields.Address(required=True), } @use_args(args) def post(self, args, network_address: str): abort_if_unknown_or_frozen_network(self.trustlines, network_address) source = args["from"] target = args["to"] max_hops = args["maxHops"] timestamp = int(time.time()) capacity, path = self.trustlines.currency_network_graphs[ network_address].find_maximum_capacity_path(source=source, target=target, max_hops=max_hops, timestamp=timestamp) return {"capacity": str(capacity), "path": path}
class OrderBook(Resource): def __init__(self, trustlines: TrustlinesRelay) -> None: self.trustlines = trustlines args = { "baseTokenAddress": fields.Address(required=True), "quoteTokenAddress": fields.Address(required=True), } @use_args(args) def get(self, args): base_token_address = to_checksum_address(args["baseTokenAddress"]) quote_token_address = to_checksum_address(args["quoteTokenAddress"]) return { "bids": OrderSchema().dump( self.trustlines.orderbook.get_bids_by_tokenpair( (base_token_address, quote_token_address)), many=True, ), "asks": OrderSchema().dump( self.trustlines.orderbook.get_asks_by_tokenpair( (base_token_address, quote_token_address)), many=True, ), }
class Path(Resource): def __init__(self, trustlines: TrustlinesRelay) -> None: self.trustlines = trustlines args = { "value": fields.Int(required=False, missing=1, validate=validate.Range(min=1)), "maxHops": fields.Int(required=False, missing=None), "maxFees": fields.Int(required=False, missing=None), "from": custom_fields.Address(required=True), "to": custom_fields.Address(required=True), "feePayer": custom_fields.FeePayerField(require=False, missing="sender"), } @use_args(args) @dump_result_with_schema(PaymentPathSchema()) def post(self, args, network_address: str): abort_if_unknown_or_frozen_network(self.trustlines, network_address) timestamp = int(time.time()) source = args["from"] target = args["to"] value = args["value"] max_fees = args["maxFees"] max_hops = args["maxHops"] fee_payer = FeePayer(args["feePayer"]) if fee_payer == FeePayer.SENDER: cost, path = self.trustlines.currency_network_graphs[ network_address].find_transfer_path_sender_pays_fees( source=source, target=target, value=value, max_fees=max_fees, max_hops=max_hops, timestamp=timestamp, ) elif fee_payer == FeePayer.RECEIVER: cost, path = self.trustlines.currency_network_graphs[ network_address].find_transfer_path_receiver_pays_fees( source=source, target=target, value=value, max_fees=max_fees, max_hops=max_hops, timestamp=timestamp, ) else: raise ValueError( f"feePayer has to be one of {[fee_payer.name for fee_payer in FeePayer]}: {fee_payer}" ) return PaymentPath(cost, path, value, fee_payer=fee_payer)
class Orders(Resource): def __init__(self, trustlines: TrustlinesRelay) -> None: self.trustlines = trustlines args = { "exchangeContractAddress": fields.Address(required=False, missing=None), "tokenAddress": fields.Address(required=False, missing=None), "makerTokenAddress": fields.Address(required=False, missing=None), "takerTokenAddress": fields.Address(required=False, missing=None), "maker": fields.Address(required=False, missing=None), "taker": fields.Address(required=False, missing=None), "trader": fields.Address(required=False, missing=None), "feeRecipient": fields.Address(required=False, missing=None), } @use_args(args) @dump_result_with_schema(OrderSchema(many=True)) def get(self, args): return self.trustlines.orderbook.get_orders( filter_exchange_address=args["exchangeContractAddress"], filter_token_address=args["tokenAddress"], filter_maker_token_address=args["makerTokenAddress"], filter_taker_token_address=args["takerTokenAddress"], filter_trader_address=args["maker"], filter_maker_address=args["taker"], filter_taker_address=args["trader"], filter_fee_recipient_address=args["feeRecipient"], )
class OrderSubmission(Resource): def __init__(self, trustlines: TrustlinesRelay) -> None: self.trustlines = trustlines args = { "exchangeContractAddress": fields.Address(required=True), "maker": fields.Address(required=True), "taker": fields.Address(required=True), "makerTokenAddress": fields.Address(required=True), "takerTokenAddress": fields.Address(required=True), "feeRecipient": fields.Address(required=True), "makerTokenAmount": fields.BigInteger(required=True), "takerTokenAmount": fields.BigInteger(required=True), "makerFee": fields.BigInteger(required=True), "takerFee": fields.BigInteger(required=True), "expirationUnixTimestampSec": fields.BigInteger(required=True), "salt": fields.BigInteger(required=True), "ecSignature": webfields.Nested( { "v": webfields.Int(required=True), "r": fields.HexBytes(required=True), "s": fields.HexBytes(required=True), }, required=True, ), } @use_args(args) def post(self, args): orderbook = self.trustlines.orderbook order = Order( exchange_address=args["exchangeContractAddress"], maker_address=args["maker"], taker_address=args["taker"], maker_token=args["makerTokenAddress"], taker_token=args["takerTokenAddress"], fee_recipient=args["feeRecipient"], maker_token_amount=args["makerTokenAmount"], taker_token_amount=args["takerTokenAmount"], maker_fee=args["makerFee"], taker_fee=args["takerFee"], expiration_timestamp_in_sec=args["expirationUnixTimestampSec"], salt=args["salt"], v=args["ecSignature"]["v"], r=args["ecSignature"]["r"], s=args["ecSignature"]["s"], ) if not order.validate_signature(): abort(422, message="Invalid ECDSA") if not orderbook.validate_exchange_address(order): abort(422, message="Invalid Exchange Address") if not orderbook.validate_timestamp(order): abort(422, message="Order already timed out") try: self.trustlines.orderbook.add_order(order) except OrderInvalidException: abort(422, message="Invalid Order")