Authorization

  1. To start working with us, the partner needs to contact us via [email protected] email. Further communication can be carried out in the agreed communication channel.

  2. There, we have to agree on the points of cooperation, i.e., which pairs, fees we will work with etc. Іmportant - clarify the type of fees (fixed/floating) for which we will work for a specific pair.

  3. The partner needs to exchange keys with our service and implement signature formation and verification of our signature in the code: the partner, on their side, generate a pair of keys (private and public keys) and send us a public key signed with their private key.

    And we, in turn, also generate a pair of keys for the partner and send them our public key signed with our private key.

    With the help of these public keys, a check is made that the request came from specific recipients.

  4. After the configuration by our team, the partner can call the API and fully work with crypto processing.

SWAPPLE API uses RSA-1024 PKCS1 keypair to secure requests.

First of all you need to generate RSA-1024 keys and send us your public key. We will send you our public key so that you can verify our response.

How to sign requests

You need to generate SHA512 hash sign based on request body.

Authentication parameters are transmitted in Headers:

  • public-key

  • signature

  • timestamp - current time in milliseconds (used in sign generation)

An example of generating a signature.

import requests
import binascii
import time
import collections
from decimal import Decimal
from Crypto.Hash import SHA512
from Crypto.Signature.pkcs1_15 import PKCS115_SigScheme
from Crypto.PublicKey import RSA

private_key = b'-----BEGIN RSA PRIVATE KEY-----\nMIICXAIagdfgadfJBdBhOb5mkijXoA/VeGqiIPVjdWth25uI\n369z434y8VMYAcmQ9a44vdutn2Zwq9dVtM35cK+etbtVo/GSDGSDGSD\n8QOIlZn+18+Hd4kWESCiycllJBsjwsNZK3PdnM7s2c6UmFuqesY3MDD/4QIDAQAB\nAoGagdfgadfgadfgadfgadfgdK//VD6lxaKvM5RNz8\nAOTc3WFefN4AnULh1T4vxq1zaPwDWhXj+y3SZjUZs6un8dZ5P6c7vqlILThy7ihJ\nCS04GRTzzybPHDU5c6eMlrm55jBpub3ajyhGgSyWgynY+RECQQC5Y/HSI18kEDWp\nerdbdc6vPs1TkhULAZOzoQXXZhDoEZjF9bRhEcbUHdiKs4+QLMjEP2CVhG/AtZ1r\nibw2A6XdAkEA8I/YzDUr1ns9jI9ZZrshblCdYu3F0Bs01Uwub36ro6LK3aVv8unz\ndxMuJQcsk+hQwnheXGsNi2/qWyC5aW2L1QJAMhEWxpx83j1ucJXOnOmk5tj8FJy4\nCB/l5rYO4MwUtsfBzXx8uVZWrwRcbaDunY4qri07hUWd9JpXqCorZR75FQJADycA\nYNx4hmn81n2xA+eFk41AXJrdet471bOWuS8hYI1AefWRt5tE2ps6rNpm1GotrBIo\n32le0QmbmWHWS+26gQJBALYrgSaKJEG4avc4fwCUF75CIZfiCUWYRSPndyQljXf0\n0XOhVNGDqFbQCtlggQ4Z+zxDoVM5LGZqw0XEIjd+/wc=\n-----END RSA PRIVATE KEY-----'
public_key = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCuNd6JS7plbbj3XvsJBdBhOb5mkijXoA/VeGqiIPVjdWth25uI369z434y8VMYAcmQ9a44vdutn2Zwq9dagdfgadfgadfbcvxn+18+Hd4kWESCiycllJBsjwsNZK3PdnM7s2c6UmFuqesY3MDD/4QIDAQAB" # no comments


SWAPPLE_ROOT_API_URL = "https://api.swapple.org/api/v3"


def request_body_to_str_line(body, timestamp):
    body = collections.OrderedDict(sorted(body.items()))
    line = ""
    for value, keys in body.items():
        if keys:
            try:
                line += value.lower() + str(Decimal(str(keys)))
            except Exception:
                line += value.lower() + str(keys).lower()
    line += "timestamp" + timestamp
    return line


def request_sign(body, timestamp):
    line = request_body_to_str_line(body, timestamp)
    new_hash = SHA512.new(line.encode())
    signer = PKCS115_SigScheme(RSA.importKey(private_key))
    sign = signer.sign(new_hash)
    return binascii.hexlify(sign).decode("utf-8")


def get_authorization_headers(body):
    timestamp = str(int(time.time()))
    signature = request_sign(body, timestamp)
    return {
        "public-key": public_key, 
        "signature": signature, 
        "timestamp": timestamp,
    }


body = {"from": "CARDUAH", "fromAmount": "5000", "to": "USDT","toNetwork": "TRX"}

requests.post(
    f"{SWAPPLE_ROOT_API_URL}/estimate-amount",
    json=body,
    headers=get_authorization_headers(body)
)

* For a more detailed understanding of request signing, please read the information below:

To make a request, the partner needs two things - a public key and a private key.

Next, the partner needs to form a request to us according to our documentation, and this request needs to be signed with the private key.

The following is a method that will turn a request:

def request_body_to_str_line(body, timestamp):
body = collections.OrderedDict(sorted(body.items()))
line = ""
for value, keys in body.items():
if keys:
try:
line += value.lower() + str(Decimal(str(keys)))
except Exception:
line += value.lower() + str(keys).lower()
line += "timestamp" + timestamp
return line

So, the output is a string to sign.

Next are two methods for signing:

def request_sign(body, timestamp):
line = request_body_to_str_line(body, timestamp)
new_hash = SHA512.new(line.encode())
signer = PKCS115_SigScheme(RSA.importKey(private_key))
sign = signer.sign(new_hash)
return binascii.hexlify(sign).decode("utf-8")

Here, body and timestamp are transferred, then the previous function is called and the next four lines form the signature:

  • hash - we take it from the string we received

  • create a signer object - the one who has to sign based on our private key

  • then we sign the hash we got in the line above

  • and return it as a string - this decodes the signature into a string.

And that's the result of the signature that needs to be added to the request.

Next, we generate a request that has a timestamp (i.e. the current time), a signature that calls the previous function and we transfer the public key, the signature we generated, and the timestamp we received and based on which we generated the signature:

def get_authorization_headers(body):
timestamp = str(int(time.time()))
signature = request_sign(body, timestamp)
return {
"public-key": public_key,
"signature": signature,
"timestamp": timestamp,
}

How to verify responses (Optional)

We sign our responses the same way you sign a request. Though this step is optional we strongly advise on verifying responses.

You will receive three parameters in headers: public-key, signature and timestamp.

An example of response verification.

import binascii
from Crypto.Hash import SHA512
from Crypto.Signature.pkcs1_15 import PKCS115_SigScheme


def response_body_to_str_line(body, timestamp):
    line = ""
        body = collections.OrderedDict(sorted(body.items()))
        for value, keys in body.items():
            line += value + keys
            
    line += "timestamp" + timestamp
    line = line.lower()
    return line

def verify_signature(body, headers):
    line = response_body_to_str_line(body, headers.get('timestamp'))
    client_sign = headers.get('signature')
    hash = SHA512.new(line.encode())
    verifier = PKCS115_SigScheme(headers.get('public-key'))
    try:
        verifier.verify(hash, binascii.unhexlify(client_sign))
        return True
    except:
        return False

Last updated