Service Example 6: External API request
Example showing how to make a REST call to an external, public API from a VM running on a Provider node.
The full code of the example is available in the yapapi repository: https://github.com/golemfactory/yapapi/tree/master/examples/external-api-request
As with the other examples, we're assuming here you already have your yagna daemon set up to request the test tasks and that you were able to configure your Python environment to run the examples using the latest version of
yapapi. If this is your first time using Golem and yapapi, please first refer to the resources linked above.
Computation Payload Manifest making use of Outbound Network requires either:
- 2.an instance of a Provider with the particular domain this example uses added to its domain whitelist
The following example will show cases 2. and 3. so it will be necessary to start a local instance of a Provider.
An example app will request an external API using Provider's network and then it will print the API response to the console.
For an app to make an Outbound Network request it needs to declare which tools it will use and which URLs it will access in a Computation Payload Manifest.
Our example will make an HTTPS request using
curlto a public REST API with the URL
Computation Payload Manifest will need to have following objects:
Example Computation Payload Manifest must follow a specific schema, and for our example it will take form of following
"name": "External API call example",
"description": "Example manifest of a service making an outbound call to the external API",
Then it needs to be encoded in
base64 --wrap=0 manifest.json > manifest.json.base64
Base64-encoded manifest can be configured using
yapapi.payload.vm.manifestfunction, resulting in following
from yapapi import Golem
from yapapi.services import Service
from yapapi.payload import vm
async def get_payload():
return await vm.manifest(
manifest = open("manifest.json.base64", "rb").read()
# later we may add here manifest signature, digest algorithm, and app author's certificate
min_mem_gib = 0.5,
min_cpu_threads = 0.5,
# capabilities used to reach Provider with a correct VM Runtime
async def run(self):
script = self._ctx.new_script()
future_result = script.run(
f"GOLEM_PRICE=`curl -X 'GET' \
-H 'accept: application/json' | jq .golem.usd`; \
echo \"Golem price: $GOLEM_PRICE USD\";",
result = (await future_result).stdout
print(result.strip() if result else "")
async def main():
async with Golem(budget=1.0, subnet_tag="testnet") as golem:
await golem.run_service(OutboundNetworkService, num_instances=1)
Providers verify the incoming request with a Computation Payload Manifest by checking if it arrives with a signature and App author's certificate signed by a certificate they trust. If there is no signature, they verify if URLs used by Computation Payload Manifest are whitelisted.
There are two ways to make our local Provider verify the request:
- Whitelisting of the domain used by the appAdd
api.coingecko.comto Provider's domain whitelist:
ya-provider whitelist add --patterns api.coingecko.com --type strict
- Signing manifest and adding signature with a certificate to the requestWith a generated and
base64-encoded certificate and a signature, the
get_payload()function takes the following form:# ...async def get_payload():return await vm.manifest(manifest = open("manifest.json.base64", "rb").read(),manifest_sig = open("manifest.json.base64.sign.sha256.base64", "rb").read(),manifest_sig_algorithm = "sha256",manifest_cert = open("golem_requestor.cert.pem.base64", "rb").read(),min_mem_gib = 0.5,min_cpu_threads = 0.5,capabilities=["inet", "manifest-support"],)# ...
With both Requestor and Provider yagna nodes and
ya-providerrunning in the background run:
(keep in mind to set
YAGNA_API_URLenv variables pointing to the local Requestor node)