Turing API Endpoints
Learn how to set up a simple endpoint for Turing to interact with
Turing can interact with any computer with an API. Examples include dozens of Google Cloud Services and AWS Services. Here are some basic instructions for using an AWS Lambda endpoint. The generic process for setting up an AWS Lambda endpoint is described here but you can also just follow along with this writeup. The generic process for setting up a Google Cloud Function is described here - the example javascript and Python code provided below also works on GCF of course.

Basic Setup

Set up an AWS account if you do not have one. Go to the Amazon Lambda web console. Click Create function (top right). Select Author from scratch. Give it a good name (e.g. basic_math). Select Runtime: Node.js 14.x (for running javascript code) or Python 3.9 (for running Python code). Leave everything else as is and click Create function (bottom right).

Add a simple test

Set up a basic test: Test > Configure test event, name the test (e.g. basic_math_test), then Create.

Add web API

Go to the Application Services section of the Amazon API Gateway web console - you can go there directly by searching for API Gateway in the service search bar (top left). Select Get Started or Create API. Chose HTTP API, Build, then Add integration - select Lambda from the dropdown - use same region; select your Lambda function (basic_math) from the dropdown. Click Create. This will give you an Invoke URL. That's what you will provide as one of the parameters for your Turing calls.

Test the system

Go back to the Lambda web console. In the Function overview, you will now see an API Gateway trigger. Click it, and then click the Triggers>API endpoint: https://.... A new browser tab will open and you will see the string "Hello from Lambda!". The basic system is now in place and working. Next, add some math, or whatever functionality you need.

Turing StableSwap example

See ./turing_stableSwap.py for deployable stableSwap code. Since AWS Lambda can run Python 3.9 you can take advantage of Python's full math support. Most obviously, you can work with floats, do not need to think about nearest integer division (//) and have the usual sqrt() and math.pow() functions to draw upon. The StableSwap code is in ./AWS_code/turing_stableSwap.py. To test it from your terminal, run:
1
#StableSwap Curl Test
2
#run from your terminal
3
curl -X POST \
4
'https://i9iznmo33e.execute-api.us-east-1.amazonaws.com/stableSwap' \
5
-H 'content-type: application/json' \
6
-d '{"L_x":"10.0","L_y":"10.0","A":"1.00","x_in":"5.00","sol":"true"}'
7
8
#returns
9
{"x_in": 5.0, "y_out": 4.227083333333334, "x_new": 15.0, "y_prev": 10.0, "y_new": 5.772916666666666, "sol": true}%
Copied!
So in this example, putting in 5.0 token 'X' would give you 4.227 token 'Y'.

Turing Simple Math Example

Assuming you set up a Node.js handler, change the index.js code to
1
// basic_math
2
exports.handler = async (event) => {
3
4
//caller provides, for example, two floats to add or multiply
5
const input = JSON.parse(event.body)
6
7
const float1 = parseFloat(input["key1"])
8
const float2 = parseFloat(input["key2"])
9
10
const sum = float1 + float2
11
const mul = float1 * float2
12
13
console.log("Sum of parameters:",sum)
14
console.log("Product of parameters:",mul)
15
16
const response = {
17
statusCode: 200,
18
body: JSON.stringify({
19
sum: sum,
20
mul: mul
21
}),
22
}
23
24
return response
25
}
Copied!
This gives you a Lambda endpoint that accepts two numbers and sums and multiplies them. This endpoint is already deployed. To test it from your terminal, run:
1
#Basic Math Curl Test
2
#run from your terminal
3
curl -X POST \
4
'https://i9iznmo33e.execute-api.us-east-1.amazonaws.com/basic_math' \
5
-H 'content-type: application/json' \
6
-d '{"key1":"0.73","key2":"9.62"}'
7
8
#returns
9
{"sum":10.35,"mul":7.022599999999999}%
Copied!

Turing Price Feed example

See ./turing_oracle.py for deployable price feed API query code. Depending on the details of the API you are interating with, you will need to make minor changes.
1
import json
2
import urllib3
3
import math
4
import textwrap
5
import struct
6
7
api_key = 'YOUR_API_KEY'
8
9
authorized_contract = None # for open access
10
# or...
11
# authorized_contract = '0xOF_YOUR_HELPER_CONTRACT' # to restrict access to only your smart contract
12
13
def lambda_handler(event, context):
14
15
input = json.loads(event["body"])
16
print("DEBUG: from Geth:", input)
17
18
# check authorisation if desired
19
callerAddress = input['method']
20
21
if authorized_contract is not None :
22
if callerAddress.lower() != authorized_contract.lower() :
23
returnPayload = {'statusCode': 403}
24
print('return payload:', returnPayload)
25
return returnPayload
26
27
# get calling parameters
28
paramsHexString = input['params'][0]
29
paramsHexString = paramsHexString.removeprefix("0x")
30
params = textwrap.wrap(paramsHexString, 64)
31
32
# 0000000000000000000000000000000000000000000000000000000000000060
33
# 0000000000000000000000000000000000000000000000000000000000000020
34
# 0000000000000000000000000000000000000000000000000000000000000007
35
# 4254432f55534400000000000000000000000000000000000000000000000000 BTC-USD, for example
36
37
str_length = int(params[2], 16) * 2
38
39
request = params[3]
40
bytes_object = bytes.fromhex(request[0:str_length])
41
pair = bytes_object.decode("ASCII")
42
43
# specify your API endpoint here
44
requestURL = 'https://api.polygon.io/v1/last/crypto/' + pair + '?apiKey=' + api_key
45
46
# Create a PoolManager instance for sending requests.
47
http = urllib3.PoolManager()
48
49
# Send a POST request and receive a HTTPResponse object.
50
resp = http.request("GET", requestURL)
51
52
print(resp.data)
53
54
result = json.loads(resp.data)
55
56
print("from endpoint:", result['last']['price'])
57
58
price = result['last']['price'] * 100
59
timestamp = result['last']['timestamp']
60
61
# create return payload
62
res = '0x'+ '{0:0{1}x}'.format(int( 64),64)
63
#64 denotes the number of bytes in the `bytes` dynamic argument
64
#since we are sending back 2 32 byte numbers, 2*32 = 64
65
res = res + '{0:0{1}x}'.format(int( price),64) #the price
66
res = res + '{0:0{1}x}'.format(int(timestamp/1000),64) #the timestamp
67
68
print("res:", res)
69
70
# example res:
71
# 0x
72
# 0000000000000000000000000000000000000000000000000000000000000040
73
# 0000000000000000000000000000000000000000000000000000000000418b95
74
# 0000000000000000000000000000000000000000000000000000017e60d3b45f
75
76
returnPayload = {
77
'statusCode': 200,
78
'body': json.dumps({
79
"result": res
80
})
81
}
82
83
print('return payload:', returnPayload)
84
85
return returnPayload
Copied!