diff --git a/.github/workflows/flux.yml b/.github/workflows/flux.yml new file mode 100644 index 0000000..8bc75be --- /dev/null +++ b/.github/workflows/flux.yml @@ -0,0 +1,69 @@ +name: build-and-push-docker-image + +on: + push: + branches: + - chore/Dockerize-Python + +permissions: + contents: write + +jobs: + build-and-push-docker-image: + runs-on: ubuntu-latest + steps: + + - name: 'Setup yq' + uses: dcarbone/install-yq-action@v1 + + - name: Checkout code + uses: actions/checkout@v2 + + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: us-east-1 + + - name: Login to ECR + id: login-ecr + uses: aws-actions/amazon-ecr-login@v1 + + - name: Get version + run: | + VERSION=$(cat API/VERSION) + echo "VERSION=${VERSION}" >> $GITHUB_ENV + + - name: Build, Tag, and Push Worker Image to Amazon ECR + env: + ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} + ECR_REPOSITORY: allora-chatbot-rag-model + IMAGE_BASE_PATH: API + VERSION: ${{ env.VERSION }} + run: | + IMAGE_TAG="${GITHUB_SHA:0:8}" + EXTRA_IMAGE_TAGS="${VERSION};latest" + + # Build and push the image to ECR with the main image tag + docker build --pull -f ${{ env.IMAGE_BASE_PATH }}/Dockerfile -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG ${{ env.IMAGE_BASE_PATH }} + docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG + + # Build and PUSH additional tags + for tag in $(echo $EXTRA_IMAGE_TAGS| tr ";" "\n"); do + docker tag $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:$tag + docker push $ECR_REGISTRY/$ECR_REPOSITORY:$tag + done + + # - name: Update Flux Repo + # env: + # VERSION: ${{ env.VERSION }} + # run: | + # git clone https://github.com/allora-network/flux-infra-offchain.git + # cd flux-infra-offchain + # git checkout main + # git pull + # yq -i '.spec.values.containers.chatbot.image.tag="$VERSION"' apps/offchain-testnet/allora-chatbot-rag-model/values.yaml + # git add apps/offchain-testnet/allora-chatbot-api/values.yaml + # git commit -m "Update allora-chatbot-api tag to $VERSION" + # git push diff --git a/components/AiButton.js b/components/AiButton.js new file mode 100644 index 0000000..0d8d1da --- /dev/null +++ b/components/AiButton.js @@ -0,0 +1,43 @@ + +import React, { useState } from "react"; +import ChatComponent from "./chatbutton1"; // Adjust the path as needed + +function AiButton() { + // State to control whether the ChatComponent is displayed + const [showChat, setShowChat] = useState(false); + + // Toggle function to open or close the chat + const toggleChat = () => { + setShowChat((prev) => !prev); + }; + + return ( +
+ {/* Render the "Ask AI" button if the chat is not shown */} + {!showChat && ( + + )} + {/* Render the ChatComponent when showChat is true, passing the onClose prop */} + {showChat && } +
+ ); +} + +export default AiButton; diff --git a/components/chatbutton1.js b/components/chatbutton1.js new file mode 100644 index 0000000..c3f3b35 --- /dev/null +++ b/components/chatbutton1.js @@ -0,0 +1,232 @@ +import React, { useState, useRef, useEffect } from "react"; + +function ChatComponent({ onClose }) { + // holds the current user input and the chat history. + const [inputMessage, setInputMessage] = useState(""); + const [chatHistory, setChatHistory] = useState([]); + const [isLoading, setIsLoading] = useState(false); + + // this references the chat history container. + const chatContainerRef = useRef(null); + + // gives an auto-scroll effect to the bottom whenever the chat history changes. + useEffect(() => { + if (chatContainerRef.current) { + chatContainerRef.current.scrollTop = chatContainerRef.current.scrollHeight; + } + }, [chatHistory]); + + // this is handler for form submission. + const handleSubmit = async (e) => { + e.preventDefault(); + + // Store the message and immediately clear the input field + const message = inputMessage; + setInputMessage(""); // Clear input immediately + + // Add user's message to the chat history. + const newUserEntry = { sender: "user", text: message }; + setChatHistory((prev) => [...prev, newUserEntry]); + + // Show loading indicator + setIsLoading(true); + + try { + // Send user's message to the FastAPI backend. + const response = await fetch("https://b832b91b8183b88b9c22eda604f1e09.testnet.allora.run/chat", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ message: message }), + }); + console.log("API went through"); + + if (!response.ok) { + throw new Error(`Server error: ${response.statusText}`); + } + + // Parse the JSON response. + const data = await response.json(); + + // Add the assistant's response to the chat history. + const newBotEntry = { + sender: "bot", + text: data.response, + sources: data.sources, + }; + setChatHistory((prev) => [...prev, newBotEntry]); + } catch (error) { + console.error("Error fetching chat response:", error); + // display an error message in the UI. + const errorEntry = { + sender: "bot", text: "Sorry, something went wrong." + }; + setChatHistory((prev) => [...prev, errorEntry]); + } finally { + // Hide loading indicator + setIsLoading(false); + } + }; + + return ( +
+ {/* Header with title and close button */} +
+

Chat with our AI

+ +
+ +
+ {chatHistory.map((entry, index) => ( +
+
+

{entry.text}

+ {entry.sources && entry.sources.length > 0 } +
+
+ ))} + + {/* Loading indicator */} + {isLoading && ( +
+
+
+
+ Thinking... +
+ +
+
+ )} +
+
+ setInputMessage(e.target.value)} + placeholder="Type your message..." + required + style={{ + flex: "1", + padding: "10px", + backgroundColor: "#333", + color: "#fff", + border: "1px solid #555", + borderRadius: "5px", + }} + /> + +
+
+ ); +} + +export default ChatComponent; \ No newline at end of file diff --git a/pages/devs/_meta.json b/pages/devs/_meta.json index c03b414..47a3c47 100644 --- a/pages/devs/_meta.json +++ b/pages/devs/_meta.json @@ -2,6 +2,7 @@ "get-started": "Get Started", "topic-creators": "Topic Creators", "consumers": "Consumers", + "sdk": "SDKs", "workers": "Workers", "reputers": "Reputers", "validators": "Validators", diff --git a/pages/devs/consumers/_meta.json b/pages/devs/consumers/_meta.json index 599e6c4..2283639 100644 --- a/pages/devs/consumers/_meta.json +++ b/pages/devs/consumers/_meta.json @@ -1,6 +1,7 @@ { "allora-api-endpoint": "Allora API Endpoint", + "rpc-data-access": "RPC Data Access", "consumer-contracts": "Consumer Contracts", "existing-consumers": "Existing Consumers", "walkthrough-use-topic-inference": "Walkthrough: Using a Topic Inference on-chain" -} \ No newline at end of file +} diff --git a/pages/devs/consumers/allora-api-endpoint.mdx b/pages/devs/consumers/allora-api-endpoint.mdx index adb45c6..e0afbe2 100644 --- a/pages/devs/consumers/allora-api-endpoint.mdx +++ b/pages/devs/consumers/allora-api-endpoint.mdx @@ -4,6 +4,42 @@ import { Callout } from 'nextra/components' The **Allora API** provides an interface to query real-time on-chain data of the latest inferences made by workers. Here's an explanation of how it works using the example endpoint: +## API Authentication + +To access the Allora API, you need to authenticate your requests using an API key. + +### Obtaining an API Key + +You can obtain an API key through the Allora API key management system. Contact the Allora team on [Discord](https://discord.com/invite/allora) for access to API keys. + +### Using an API Key + +Once you have an API key, you can include it in your API requests using the `x-api-key` header: + +```bash +curl -X 'GET' \ + --url 'https://api.allora.network/v2/allora/consumer/?allora_topic_id=' \ + -H 'accept: application/json' \ + -H 'x-api-key: ' +``` + +Replace `` with your actual API key, `` with the chain ID (e.g., `ethereum-11155111` for Sepolia), and `` with the topic ID you want to query. + +### API Key Security + +Your API key is a sensitive credential that should be kept secure. Do not share your API key or commit it to version control systems. Instead, use environment variables or secure credential storage mechanisms to manage your API key. + +```javascript +// Example of using an environment variable for API key +const apiKey = process.env.ALLORA_API_KEY; +``` + +### Rate Limiting + +API requests are subject to rate limiting. If you exceed the rate limit, you will receive a 429 Too Many Requests response. To avoid rate limiting issues, consider implementing retry logic with exponential backoff in your applications. + +## API Endpoints + **Generic**: `https://allora-api.testnet.allora.network/emissions/{version_number}/latest_network_inferences/{topic_id}` **Example**: `https://allora-api.testnet.allora.network/emissions/v7/latest_network_inferences/1` diff --git a/pages/devs/consumers/rpc-data-access.mdx b/pages/devs/consumers/rpc-data-access.mdx new file mode 100644 index 0000000..3c902ff --- /dev/null +++ b/pages/devs/consumers/rpc-data-access.mdx @@ -0,0 +1,194 @@ +import { Callout } from 'nextra/components' + +# Accessing Allora Data Through RPC + +In addition to the [Allora API](/devs/consumers/allora-api-endpoint), you can also access Allora network data directly through RPC (Remote Procedure Call) endpoints. This provides an alternative method for consuming outputs from the network, especially useful for applications that need to interact directly with the blockchain. + +## Prerequisites + +- [`allorad` CLI](/devs/get-started/cli) installed +- Access to an Allora RPC node + +For a complete list of available RPC endpoints and commands, see the [allorad reference section](/devs/reference/allorad). + +## RPC URL and Chain ID + +Each network uses a different RPC URL and Chain ID which are needed to specify which network to run commands on when using specific commands on allorad. + +### Testnet +- **RPC URLs**: + - `https://rpc.ankr.com/allora_testnet` + - `https://allora-rpc.testnet.allora.network/` +- **Chain ID**: `allora-testnet-1` + +## RPC Endpoints for Consumers + +The following RPC methods are particularly useful for consumers looking to access inference data from the Allora network: + +### Get Latest Available Network Inferences + +This is the primary method for consumers to retrieve the latest network inference for a specific topic. + +```bash +allorad q emissions latest-available-network-inferences [topic_id] --node +``` + +**Parameters:** +- `topic_id`: The identifier of the topic for which you want to retrieve the latest available network inference. +- `RPC_URL`: The URL of the RPC node you're connecting to. + +**Example:** +```bash +allorad q emissions latest-available-network-inferences 1 --node https://allora-rpc.testnet.allora.network/ +``` + +**Response:** +The response includes the network inference data, including the combined value, individual worker values, confidence intervals, and more. Here's a simplified example: + +```json +{ + "network_inferences": { + "topic_id": "1", + "combined_value": "2605.533879185080648394998043723508", + "inferer_values": [ + { + "worker": "allo102ksu3kx57w0mrhkg37kvymmk2lgxqcan6u7yn", + "value": "2611.01109296" + }, + { + "worker": "allo10q6hm2yae8slpvvgmxqrcasa30gu5qfysp4wkz", + "value": "2661.505295679922" + } + ], + "naive_value": "2605.533879185080648394998043723508" + }, + "confidence_interval_values": [ + "2492.1675618299669694181830608795809", + "2543.9249467952655499150756965734158", + "2611.033130351115229549044053766836", + "2662.29523395638446190095015123294396", + "2682.827040221238" + ] +} +``` + + +The `combined_value` field represents the optimized inference that takes both naive submissions and forecast data into account. This is typically the value you want to use for most consumer applications. + + +## Using RPC in Your Applications + +### JavaScript/TypeScript Example + +Here's an example of how to query the Allora network using RPC in a JavaScript/TypeScript application: + +```typescript +import axios from 'axios'; + +async function getLatestInference(topicId: number, rpcUrl: string) { + try { + const response = await axios.post(rpcUrl, { + jsonrpc: '2.0', + id: 1, + method: 'abci_query', + params: { + path: `/allora.emissions.v1.Query/GetLatestAvailableNetworkInferences`, + data: Buffer.from(JSON.stringify({ topic_id: topicId })).toString('hex'), + prove: false + } + }); + + // Parse the response + const result = response.data.result; + if (result.response.code !== 0) { + throw new Error(`Query failed with code ${result.response.code}`); + } + + // Decode the response value + const decodedValue = Buffer.from(result.response.value, 'base64').toString(); + const parsedValue = JSON.parse(decodedValue); + + return parsedValue; + } catch (error) { + console.error('Error querying Allora RPC:', error); + throw error; + } +} + +// Example usage +getLatestInference(1, 'https://allora-rpc.testnet.allora.network/') + .then(data => { + console.log('Latest inference:', data.network_inferences.combined_value); + console.log('Confidence intervals:', data.confidence_interval_values); + }) + .catch(error => { + console.error('Failed to get inference:', error); + }); +``` + +### Python Example + +Here's an example of how to query the Allora network using RPC in a Python application: + +```python +import requests +import json +import base64 + +def get_latest_inference(topic_id, rpc_url): + try: + payload = { + "jsonrpc": "2.0", + "id": 1, + "method": "abci_query", + "params": { + "path": "/allora.emissions.v1.Query/GetLatestAvailableNetworkInferences", + "data": bytes(json.dumps({"topic_id": topic_id}), 'utf-8').hex(), + "prove": False + } + } + + response = requests.post(rpc_url, json=payload) + response.raise_for_status() + + result = response.json()["result"] + if result["response"]["code"] != 0: + raise Exception(f"Query failed with code {result['response']['code']}") + + # Decode the response value + decoded_value = base64.b64decode(result["response"]["value"]).decode('utf-8') + parsed_value = json.loads(decoded_value) + + return parsed_value + except Exception as e: + print(f"Error querying Allora RPC: {e}") + raise + +# Example usage +try: + data = get_latest_inference(1, "https://allora-rpc.testnet.allora.network/") + print(f"Latest inference: {data['network_inferences']['combined_value']}") + print(f"Confidence intervals: {data['confidence_interval_values']}") +except Exception as e: + print(f"Failed to get inference: {e}") +``` + +## RPC vs API: When to Use Each + +### Use RPC When: + +- You need direct blockchain access without intermediaries +- You want to query historical data that might not be available through the API +- You're building applications that need to interact with multiple aspects of the Allora network +- You want to avoid potential rate limiting on the API + +### Use the API When: + +- You need a simpler interface with standardized authentication +- You want to avoid the complexity of RPC calls +- You're primarily interested in the latest inference data +- You need additional features provided by the API that aren't available through RPC + + +RPC nodes may have their own rate limiting or access restrictions. Make sure to implement proper error handling and retry logic in your applications. + diff --git a/pages/devs/consumers/walkthrough-use-topic-inference.mdx b/pages/devs/consumers/walkthrough-use-topic-inference.mdx index c09cb57..cc6c78c 100644 --- a/pages/devs/consumers/walkthrough-use-topic-inference.mdx +++ b/pages/devs/consumers/walkthrough-use-topic-inference.mdx @@ -32,11 +32,14 @@ Follow these instructions to bring the most recent inference data on-chain for a ## Step by Step Guide: -1. Create an Upshot API key by [creating an account](https://developer.upshot.xyz/signup). -2. Call the Consumer Inference API using the `topicId` found in the [deployed topics list](/devs/get-started/existing-topics) and the correct chainId. For example, if you use sepolia, you would provide `ethereum-11155111`. +Call the Consumer Inference API using the `asset` and `timeframe` you want to query. + +- `asset` is the asset you want to query, e.g. `BTC`, `ETH` +- `timeframe` is the timeframe you want to query, e.g. `5m`, `8h` ```shell -curl -X 'GET' --url 'https://api.upshot.xyz/v2/allora/consumer/?allora_topic_id=' -H 'accept: application/json' -H 'x-api-key: ' + +curl -X 'GET' --url 'https://api.allora.network/v2/allora/consumer/price/ethereum-111551111/ETH/5m' -H 'x-api-key: ' ``` Here is an example response: diff --git a/pages/devs/get-started/basic-usage.mdx b/pages/devs/get-started/basic-usage.mdx index d125b58..2fa4bfd 100644 --- a/pages/devs/get-started/basic-usage.mdx +++ b/pages/devs/get-started/basic-usage.mdx @@ -8,7 +8,7 @@ Despite the complexities involved in the setup and operation of different partic Interacting with the Allora Network also involves querying data of existing topics on-chain. This can be efficiently done using the Allorad CLI tool. The CLI tool provides a command-line interface to interact with the network, enabling users to retrieve on-chain data seamlessly. -Follow the tutorial [here](/devs/consumers/onchain-query-existing-data) to learn how to query an inference on-chain using the `allorad` CLI tool. +Follow the tutorial [here](/devs/get-started/query-network-data#get-latest-available-network-inferences) to learn how to query an inference on-chain using the `allorad` CLI tool. ## Delegating Stake to a Reputer diff --git a/pages/devs/get-started/model-forge.mdx b/pages/devs/get-started/model-forge.mdx index 9a3d6a0..8976dc7 100644 --- a/pages/devs/get-started/model-forge.mdx +++ b/pages/devs/get-started/model-forge.mdx @@ -74,7 +74,7 @@ Topics are assigned an ID and categorized by a specific Target Variable, Epoch, - **Epoch**: A discrete period during which inferences and forecasts are submitted, and rewards are distributed. - Epochs are defined in blocks on the Network - Each epoch provides a timeframe for evaluating and scoring the performance of workers and reputers. - - In the Forge Competition, epochs are are abstracted into universal timeframes, e.g. `5min`, `1hr`, `1d`. + - In the Forge Competition, epochs are abstracted into universal timeframes, e.g. `5min`, `1hr`, `1d`. - **Loss Function**: Measures how far off your model's predictions are from the actual values - For all topics in the Forge Competition, the loss function is [`Mean Squared Error`](https://en.wikipedia.org/wiki/Mean_squared_error). - **Metadata**: Additional information about the topic, including the financial indicator, prediction period, and target variable. diff --git a/pages/devs/sdk/_meta.json b/pages/devs/sdk/_meta.json new file mode 100644 index 0000000..82a73a6 --- /dev/null +++ b/pages/devs/sdk/_meta.json @@ -0,0 +1,5 @@ +{ + "overview": "Overview", + "allora-sdk-ts": "TypeScript SDK", + "allora-sdk-py": "Python SDK" +} diff --git a/pages/devs/sdk/allora-sdk-py.mdx b/pages/devs/sdk/allora-sdk-py.mdx new file mode 100644 index 0000000..2b4ed53 --- /dev/null +++ b/pages/devs/sdk/allora-sdk-py.mdx @@ -0,0 +1,240 @@ +import { Callout } from 'nextra/components' + +# Allora Python SDK + +The Allora Python SDK provides a convenient way to interact with the Allora API from Python applications. + +## Installation + +You can install the Allora Python SDK using pip: + +```bash +pip install allora_sdk +``` + +## Basic Usage + +Here's how to use the Allora Python SDK: + +```python +from allora_sdk import AlloraClient + +# Initialize the client +client = AlloraClient( + chain="testnet", # Use "mainnet" for mainnet + api_key="YOUR_API_KEY" # Optional, but recommended for production use +) + +# Fetch all available topics +def fetch_topics(): + try: + topics = client.get_all_topics() + print(f"Available topics: {topics}") + except Exception as e: + print(f"Error fetching topics: {e}") + +# Fetch inference for a specific topic +def fetch_inference(topic_id): + try: + inference = client.get_inference_by_topic_id(topic_id) + print(f"Inference data: {inference}") + except Exception as e: + print(f"Error fetching inference: {e}") + +# Fetch price inference for a specific asset and timeframe +def fetch_price_inference(): + try: + inference = client.get_price_inference( + asset="BTC", + timeframe="8h" + ) + print(f"Price inference data: {inference}") + except Exception as e: + print(f"Error fetching price inference: {e}") +``` + +## API Reference + +### `AlloraClient` + +The main class for interacting with the Allora API. + +#### Constructor + +```python +def __init__(self, chain="testnet", api_key=None, base_api_url=None): + """ + Initialize the Allora API client. + + Args: + chain (str): The chain to use. Can be "testnet" or "mainnet". + api_key (str, optional): Your API key. Recommended for production use. + base_api_url (str, optional): The base URL for the API. + """ +``` + +#### Methods + +##### `get_all_topics()` + +Fetches all available topics from the Allora API. + +```python +def get_all_topics(self): + """ + Fetch all available topics from the Allora API. + + Returns: + list: A list of all available topics. + + Raises: + Exception: If the API request fails. + """ +``` + +##### `get_inference_by_topic_id(topic_id, signature_format="ethereum-11155111")` + +Fetches an inference for a specific topic from the Allora API. + +```python +def get_inference_by_topic_id(self, topic_id, signature_format="ethereum-11155111"): + """ + Fetch an inference for a specific topic from the Allora API. + + Args: + topic_id (int): The unique identifier of the topic to get inference for. + signature_format (str, optional): The format of the signature. + Defaults to "ethereum-11155111". + + Returns: + dict: The inference data. + + Raises: + Exception: If the API request fails. + """ +``` + +##### `get_price_inference(asset, timeframe, signature_format="ethereum-11155111")` + +Fetches a price inference for a specific asset and timeframe from the Allora API. + +```python +def get_price_inference(self, asset, timeframe, signature_format="ethereum-11155111"): + """ + Fetch a price inference for a specific asset and timeframe from the Allora API. + + Args: + asset (str): The asset to get price inference for. Can be "BTC" or "ETH". + timeframe (str): The timeframe to get price inference for. Can be "5m" or "8h". + signature_format (str, optional): The format of the signature. + Defaults to "ethereum-11155111". + + Returns: + dict: The inference data. + + Raises: + Exception: If the API request fails. + """ +``` + +## Examples + +### Fetching and Using Price Inference + +```python +import os +from allora_sdk import AlloraClient + +# Initialize the client +client = AlloraClient( + chain="testnet", + api_key=os.environ.get("ALLORA_API_KEY") +) + +try: + # Fetch BTC price inference for 8-hour timeframe + inference = client.get_price_inference( + asset="BTC", + timeframe="8h" + ) + + # Extract the network inference value + network_inference = inference["inference_data"]["network_inference"] + print(f"BTC 8-hour price inference: {network_inference}") + + # Extract confidence interval values + confidence_intervals = inference["inference_data"]["confidence_interval_values"] + print("Confidence intervals:", confidence_intervals) + + # Use the inference data in your application + # ... +except Exception as e: + print(f"Error fetching BTC price inference: {e}") +``` + +### Fetching All Topics and Displaying Them + +```python +import os +from allora_sdk import AlloraClient + +# Initialize the client +client = AlloraClient( + chain="testnet", + api_key=os.environ.get("ALLORA_API_KEY") +) + +try: + # Fetch all topics + topics = client.get_all_topics() + + # Display topics + print(f"Found {len(topics)} topics:") + for topic in topics: + print(f"- Topic ID: {topic['topic_id']}") + print(f" Name: {topic['topic_name']}") + print(f" Description: {topic.get('description', 'No description')}") + print(f" Active: {'Yes' if topic.get('is_active') else 'No'}") + print(f" Worker count: {topic['worker_count']}") + print(f" Updated at: {topic['updated_at']}") + print("---") +except Exception as e: + print(f"Error fetching topics: {e}") +``` + +### Using Inference Data in a Web Application + +```python +from flask import Flask, jsonify +import os +from allora_sdk import AlloraClient + +app = Flask(__name__) + +# Initialize the client +client = AlloraClient( + chain="testnet", + api_key=os.environ.get("ALLORA_API_KEY") +) + +@app.route('/api/price/btc') +def get_btc_price(): + try: + # Fetch BTC price inference + inference = client.get_price_inference( + asset="BTC", + timeframe="8h" + ) + + # Extract the network inference value and confidence intervals + return jsonify({ + 'price': inference["inference_data"]["network_inference"], + 'confidence_intervals': inference["inference_data"]["confidence_interval_values"], + 'timestamp': inference["inference_data"]["timestamp"] + }) + except Exception as e: + return jsonify({'error': str(e)}), 500 + +if __name__ == '__main__': + app.run(debug=True) +``` diff --git a/pages/devs/sdk/allora-sdk-ts.mdx b/pages/devs/sdk/allora-sdk-ts.mdx new file mode 100644 index 0000000..b5f0b40 --- /dev/null +++ b/pages/devs/sdk/allora-sdk-ts.mdx @@ -0,0 +1,360 @@ +import { Callout } from 'nextra/components' + +# Allora TypeScript SDK + +The Allora TypeScript SDK provides a convenient way to interact with the Allora API from JavaScript and TypeScript applications. + +## Installation + +You can install the Allora TypeScript SDK using npm or yarn: + +```bash +# Using npm +npm install @alloralabs/allora-sdk + +# Using yarn +yarn add @alloralabs/allora-sdk +``` + +## Basic Usage + +Here's a simple example of how to use the Allora TypeScript SDK: + +```typescript +import { AlloraAPIClient, ChainSlug } from '@alloralabs/allora-sdk/v2' + +// Initialize the client +const alloraClient = new AlloraAPIClient({ + chainSlug: ChainSlug.TESTNET, // Use ChainSlug.MAINNET for mainnet + apiKey: process.env.ALLORA_API_KEY, // Optional, but recommended for production use +}); + +// Fetch all available topics +async function fetchTopics() { + try { + const topics = await alloraClient.getAllTopics(); + console.log('Available topics:', topics); + } catch (error) { + console.error('Error fetching topics:', error); + } +} + +// Fetch inference for a specific topic +async function fetchInference(topicId: number) { + try { + const inference = await alloraClient.getInferenceByTopicID(topicId); + console.log('Inference data:', inference); + } catch (error) { + console.error('Error fetching inference:', error); + } +} + +// Fetch price inference for a specific asset and timeframe +async function fetchPriceInference() { + try { + const inference = await alloraClient.getPriceInference( + PriceInferenceToken.BTC, + PriceInferenceTimeframe.EIGHT_HOURS + ); + console.log('Price inference data:', inference); + } catch (error) { + console.error('Error fetching price inference:', error); + } +} +``` + + +The API key is optional but recommended for production use. If not provided, a default API key will be used, which may be subject to rate limiting. + + +## API Reference + +### `AlloraAPIClient` + +The main class for interacting with the Allora API. + +#### Constructor + +```typescript +constructor(config: AlloraAPIClientConfig) +``` + +Parameters: +- `config`: An object with the following properties: + - `chainSlug`: The chain to use. Can be `ChainSlug.TESTNET` or `ChainSlug.MAINNET`. + - `apiKey`: Your API key. Optional, but recommended for production use. + - `baseAPIUrl`: The base URL for the API. Optional, defaults to `https://api.allora.network/v2`. + +#### Methods + +##### `getAllTopics()` + +Fetches all available topics from the Allora API. + +```typescript +async getAllTopics(): Promise +``` + +Returns: A promise that resolves to an array of all available topics. + +##### `getInferenceByTopicID(topicID, signatureFormat)` + +Fetches an inference for a specific topic from the Allora API. + +```typescript +async getInferenceByTopicID( + topicID: number, + signatureFormat: SignatureFormat = SignatureFormat.ETHEREUM_SEPOLIA +): Promise +``` + +Parameters: +- `topicID`: The unique identifier of the topic to get inference for. +- `signatureFormat`: The format of the signature. Optional, defaults to `SignatureFormat.ETHEREUM_SEPOLIA`. + +Returns: A promise that resolves to the inference data. + +##### `getPriceInference(asset, timeframe, signatureFormat)` + +Fetches a price inference for a specific asset and timeframe from the Allora API. + +```typescript +async getPriceInference( + asset: PriceInferenceToken, + timeframe: PriceInferenceTimeframe, + signatureFormat: SignatureFormat = SignatureFormat.ETHEREUM_SEPOLIA +): Promise +``` + +Parameters: +- `asset`: The asset to get price inference for. Can be `PriceInferenceToken.BTC` or `PriceInferenceToken.ETH`. +- `timeframe`: The timeframe to get price inference for. Can be `PriceInferenceTimeframe.FIVE_MIN` or `PriceInferenceTimeframe.EIGHT_HOURS`. +- `signatureFormat`: The format of the signature. Optional, defaults to `SignatureFormat.ETHEREUM_SEPOLIA`. + +Returns: A promise that resolves to the inference data. + +### Enums + +#### `ChainSlug` + +```typescript +enum ChainSlug { + TESTNET = "testnet", + MAINNET = "mainnet", +} +``` + +#### `PriceInferenceToken` + +```typescript +enum PriceInferenceToken { + BTC = "BTC", + ETH = "ETH", +} +``` + +#### `PriceInferenceTimeframe` + +```typescript +enum PriceInferenceTimeframe { + FIVE_MIN = "5m", + EIGHT_HOURS = "8h", +} +``` + +#### `SignatureFormat` + +```typescript +enum SignatureFormat { + ETHEREUM_SEPOLIA = "ethereum-11155111", +} +``` + +### Interfaces + +#### `AlloraAPIClientConfig` + +```typescript +interface AlloraAPIClientConfig { + chainSlug?: ChainSlug; + apiKey?: string; + baseAPIUrl?: string; +} +``` + +#### `AlloraTopic` + +```typescript +interface AlloraTopic { + topic_id: number; + topic_name: string; + description?: string | null; + epoch_length: number; + ground_truth_lag: number; + loss_method: string; + worker_submission_window: number; + worker_count: number; + reputer_count: number; + total_staked_allo: number; + total_emissions_allo: number; + is_active: boolean | null; + updated_at: string; +} +``` + +#### `AlloraInferenceData` + +```typescript +interface AlloraInferenceData { + network_inference: string; + network_inference_normalized: string; + confidence_interval_percentiles: string[]; + confidence_interval_percentiles_normalized: string[]; + confidence_interval_values: string[]; + confidence_interval_values_normalized: string[]; + topic_id: string; + timestamp: number; + extra_data: string; +} +``` + +#### `AlloraInference` + +```typescript +interface AlloraInference { + signature: string; + inference_data: AlloraInferenceData; +} +``` + +## Examples + +### Fetching and Using Price Inference + +```typescript +import { AlloraAPIClient, ChainSlug, PriceInferenceToken, PriceInferenceTimeframe } from '@alloralabs/allora-sdk/v2' + +async function fetchAndUseBTCPriceInference() { + // Initialize the client + const alloraClient = new AlloraAPIClient({ + chainSlug: ChainSlug.TESTNET, + apiKey: process.env.ALLORA_API_KEY, + }); + + try { + // Fetch BTC price inference for 8-hour timeframe + const inference = await alloraClient.getPriceInference( + PriceInferenceToken.BTC, + PriceInferenceTimeframe.EIGHT_HOURS + ); + + // Extract the network inference value + const networkInference = inference.inference_data.network_inference; + console.log(`BTC 8-hour price inference: ${networkInference}`); + + // Extract confidence interval values + const confidenceIntervals = inference.inference_data.confidence_interval_values; + console.log('Confidence intervals:', confidenceIntervals); + + // Use the inference data in your application + // ... + } catch (error) { + console.error('Error fetching BTC price inference:', error); + } +} +``` + +### Fetching All Topics and Displaying Them + +```typescript +import { AlloraAPIClient, ChainSlug } from '@alloralabs/allora-sdk/v2' + +async function displayAllTopics() { + // Initialize the client + const alloraClient = new AlloraAPIClient({ + chainSlug: ChainSlug.TESTNET, + apiKey: process.env.ALLORA_API_KEY, + }); + + try { + // Fetch all topics + const topics = await alloraClient.getAllTopics(); + + // Display topics + console.log(`Found ${topics.length} topics:`); + topics.forEach(topic => { + console.log(`- Topic ID: ${topic.topic_id}`); + console.log(` Name: ${topic.topic_name}`); + console.log(` Description: ${topic.description || 'No description'}`); + console.log(` Active: ${topic.is_active ? 'Yes' : 'No'}`); + console.log(` Worker count: ${topic.worker_count}`); + console.log(` Updated at: ${topic.updated_at}`); + console.log('---'); + }); + } catch (error) { + console.error('Error fetching topics:', error); + } +} +``` + +### Using Inference Data with React + +```typescript +import React, { useState, useEffect } from 'react'; +import { AlloraAPIClient, ChainSlug, PriceInferenceToken, PriceInferenceTimeframe } from '@alloralabs/allora-sdk/v2'; + +function PriceDisplay() { + const [price, setPrice] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + const fetchPrice = async () => { + try { + setLoading(true); + + // Initialize the client + const alloraClient = new AlloraAPIClient({ + chainSlug: ChainSlug.TESTNET, + apiKey: process.env.REACT_APP_ALLORA_API_KEY, + }); + + // Fetch ETH price inference + const inference = await alloraClient.getPriceInference( + PriceInferenceToken.ETH, + PriceInferenceTimeframe.FIVE_MIN + ); + + // Set the price + setPrice(inference.inference_data.network_inference); + setError(null); + } catch (err) { + setError('Failed to fetch price data'); + console.error(err); + } finally { + setLoading(false); + } + }; + + fetchPrice(); + + // Refresh price every 5 minutes + const intervalId = setInterval(fetchPrice, 5 * 60 * 1000); + + // Clean up interval on component unmount + return () => clearInterval(intervalId); + }, []); + + if (loading) return
Loading price data...
; + if (error) return
Error: {error}
; + + return ( +
+

Current ETH Price

+

{price}

+
+ ); +} + +export default PriceDisplay; +``` diff --git a/pages/devs/sdk/overview.mdx b/pages/devs/sdk/overview.mdx new file mode 100644 index 0000000..13f96af --- /dev/null +++ b/pages/devs/sdk/overview.mdx @@ -0,0 +1,10 @@ +# Allora SDKs + +Allora provides Software Development Kits (SDKs) in multiple programming languages to make it easier to integrate with the Allora network. These SDKs provide a convenient way to interact with the Allora API and consume inferences from the network. + +Currently, the following SDKs are available: + +- [TypeScript SDK](/devs/sdk/allora-sdk-ts) - For JavaScript and TypeScript applications +- [Python SDK](/devs/sdk/allora-sdk-py) - For Python applications + +Choose the SDK that best fits your development environment and follow the getting started guide to begin integrating with Allora. diff --git a/pages/devs/workers/deploy-worker/allora-mdk.mdx b/pages/devs/workers/deploy-worker/allora-mdk.mdx index 4b2bdf3..c4301cd 100644 --- a/pages/devs/workers/deploy-worker/allora-mdk.mdx +++ b/pages/devs/workers/deploy-worker/allora-mdk.mdx @@ -37,8 +37,8 @@ Although these models are already integrated into the MDK, you can add more mode Run the following commands in a new terminal window: ```bash -git clone https://github.com/allora-network/allora-model-maker.git -cd allora-model-maker +git clone https://github.com/allora-network/allora-mdk.git +cd allora-mdk ``` #### Conda not Installed? @@ -190,31 +190,11 @@ Replace arima with the name of the model you’d like to package (e.g., lstm, xg This will: -- Copy the model’s files and dependencies into the `packaged_models/package folder`. -- Run test's for inference and training to validate funtionality in a worker +- Copy the model’s files and dependencies into the `package folder`. +- Run test's for inference and training to validate functionality in a worker - Generate a configuration file, `config.py`, that contains the active model information. -### Clone the Allora Worker Repository - -Run the following commands in a new terminal window: - -```bash -git clone https://github.com/allora-network/allora-worker.git -cd allora-worker -``` - -### Integrate your Model - -After running the packaging command: - -1. Navigate to the packaged_models folder in your allora-model-maker repo. -2. Copy the package folder into the src folder of your allora-worker repository. - - -If you did this right in your allora-worker repo you'll now have `allora-worker/src/package` - - ### Deploy your Worker #### Expose the Endpoint diff --git a/pages/home/_meta.json b/pages/home/_meta.json index b004d35..9c9c22c 100644 --- a/pages/home/_meta.json +++ b/pages/home/_meta.json @@ -5,6 +5,7 @@ "participants": "Participants", "layers": "Layers of the Network", "tokenomics": "Tokenomics", + "delegating-stake": "Delegating Stake", "confidence-intervals": "Confidence Intervals", "release-notes": "Release Notes", "whitepaper": { diff --git a/pages/home/delegating-stake.mdx b/pages/home/delegating-stake.mdx new file mode 100644 index 0000000..e76c1de --- /dev/null +++ b/pages/home/delegating-stake.mdx @@ -0,0 +1,44 @@ +# Delegating Stake on the Allora Network + +Delegating stake on the Allora Network is a way to earn passive rewards by supporting a reputer's operations. When you delegate funds to a reputer, you enhance their stake, which improves the security of topics and increases the accuracy of loss reports. In return, you receive rewards based on the reputer's performance. + +## Why Delegate Stake? + +- Passive Earnings: Delegators earn a portion of the rewards generated by the reputer's success. +- Enhanced Security: Your stake contributes to the overall security and trustworthiness of the Allora Network. +- Improved Accuracy: Higher stakes allow reputers to provide more accurate loss reports. +- Withdrawal Safeguard: A withdrawal delay is in place to prevent quick attacks and ensure network stability. + +## How to Delegate Stake + +Follow these steps to delegate your stake to a reputer node: + +### Visit the Allora Explorer + +- Go to explorer.allora.network. + +### Connect Your Wallet + +- Click on the "Connect Wallet" button at the top right of the page. +- Choose your preferred wallet (Keplr, Leap) and connect to the network. + +### Navigate to Staking + +- Once connected, go to the "Staking" section from the navigation menu. + +### Select a Reputer + +- Browse the list of available reputer nodes. +- Choose a reputer based on their performance metrics and reliability. + +### Delegate Your Stake + +- Click the "Delegate" button next to the chosen reputer. + +- Enter the amount you want to delegate. + +- Confirm the transaction in your wallet. + +### Monitor Your Delegation: + +- Track your stake and rewards over time in the explorer's dashboard. diff --git a/pages/home/explore.mdx b/pages/home/explore.mdx index 4986512..667ee98 100644 --- a/pages/home/explore.mdx +++ b/pages/home/explore.mdx @@ -41,8 +41,9 @@ There are a few easy things a user could do to interact with the Allora Network + - + diff --git a/pages/home/layers/forecast-synthesis.mdx b/pages/home/layers/forecast-synthesis.mdx index d16de1f..9c90a31 100644 --- a/pages/home/layers/forecast-synthesis.mdx +++ b/pages/home/layers/forecast-synthesis.mdx @@ -1,5 +1,5 @@ # Forecast and Synthesis -Inferences are scored by forecast workers and combined by the topic cooordinator to deliver a single synthesized inference to the consumer that is a weighted combination of all individual inferences. +Inferences are scored by forecast workers and combined by the topic coordinator to deliver a single synthesized inference to the consumer that is a weighted combination of all individual inferences. -Let's dive into this process in the following sections. \ No newline at end of file +Let's dive into this process in the following sections. diff --git a/pages/marketplace/explore.mdx b/pages/marketplace/explore.mdx index be0e688..4ce7d5d 100644 --- a/pages/marketplace/explore.mdx +++ b/pages/marketplace/explore.mdx @@ -2,15 +2,19 @@ import { Cards, Card, Callout } from 'nextra/components' # Explore Allora's Marketplace -Allora's marketplace is a platform for developers to build and publish integrations for the Allora network. +Allora's marketplace is a set of plugins for developers to build and publish integrations using the Allora network. ## Integrations - - - - +- ### [Eliza OS](https://github.com/elizaOS/eliza/tree/main/packages/plugin-allora) + A powerful operating system plugin that enables seamless interaction with Eliza-based systems. -## Prerequisites +- ### [GOAT SDK](https://www.npmjs.com/package/@goat-sdk/plugin-allora) + Software Development Kit for building and deploying GOAT applications. + +- ### [Zerepy SDK](https://github.com/blorm-network/ZerePy/blob/52d86b0151049ab2f2880e60207e6012ffd60829/src/connections/allora_connection.py#L15) + Python SDK for building and deploying Zerepy applications. + +- ### [Virtuals SDK](https://github.com/game-by-virtuals/game-node/tree/main/plugins/alloraPlugin) + A plugin for the Game Agent that enables seamless interaction with Allora. -- Grab an [Allora API Key](https://developer.upshot.xyz) before you start. This is required to use the plugin. diff --git a/pages/marketplace/integrations/eliza-os/example-usage.mdx b/pages/marketplace/integrations/eliza-os/example-usage.mdx index 8bbb1b0..ae3e8c2 100644 --- a/pages/marketplace/integrations/eliza-os/example-usage.mdx +++ b/pages/marketplace/integrations/eliza-os/example-usage.mdx @@ -9,7 +9,6 @@ This example will show you how to use the Allora Network plugin for Eliza OS by - Node 23.3 - [Python 2.7+](https://www.python.org/downloads/) - [`pnpm`](https://pnpm.io/installation) -- [Allora API Key](https://developer.upshot.xyz) ## Download and Install Eliza OS @@ -28,16 +27,9 @@ cp .env.example .env ### Change Allora API Key and Chain ID -In your `.env` file, change the `ALLORA_API_KEY` and `CHAIN_ID` to your Allora API Key and Chain ID (Chain ID is the Allora Network chain you want to interact with, e.g. `testnet` or `mainnet`). - - -You can get your Allora API Key from the [Allora Developer Dashboard](https://developer.upshot.xyz). - +In your `.env` file, change the `CHAIN_ID` to your Chain ID (Chain ID is the Allora Network chain you want to interact with, e.g. `testnet` or `mainnet`). ```bash -# Allora API Key -ALLORA_API_KEY= - # Chain ID CHAIN_ID= ``` diff --git a/pages/marketplace/integrations/goat-sdk.mdx b/pages/marketplace/integrations/goat-sdk.mdx index 7867fd0..9a535a6 100644 --- a/pages/marketplace/integrations/goat-sdk.mdx +++ b/pages/marketplace/integrations/goat-sdk.mdx @@ -21,19 +21,12 @@ As a Goat developer, this plugin enables you to: npm install @goat-sdk/plugin-allora ``` -## Environment Variables - -- `ALLORA_API_KEY`: Your Allora API key. This is required to use the plugin. - - [Get your API key](https://developer.upshot.xyz) - ## Setup ```typescript import { allora } from '@goat-sdk/plugin-allora' -const plugin = allora({ - apiKey: process.env.ALLORA_API_KEY, -}) +const plugin = allora() ``` ## Available Actions diff --git a/theme.config.tsx b/theme.config.tsx index 16c46ea..7c6bf10 100644 --- a/theme.config.tsx +++ b/theme.config.tsx @@ -1,6 +1,9 @@ +// theme.config.tsx +import React from 'react' import { useRouter } from 'next/router' -import { DocsThemeConfig, useConfig } from "nextra-theme-docs"; -import React from "react"; +import Link from 'next/link' +import { DocsThemeConfig, useConfig } from 'nextra-theme-docs' +import AiButton from './components/AiButton.js' const config: DocsThemeConfig = { useNextSeoProps() { @@ -16,8 +19,7 @@ const config: DocsThemeConfig = { return ( <> - - + ) @@ -26,7 +28,6 @@ const config: DocsThemeConfig = { head: function useHead() { const { title } = useConfig() const socialCard = '/allora-link-preview' - return ( <> @@ -64,16 +65,25 @@ const config: DocsThemeConfig = { chat: { link: 'https://discord.com/invite/allora' }, + // fixed-position container. footer: { - component: (<>) + component: () => ( +
+ +
+ ), }, sidebar: { autoCollapse: true, }, - // ... other theme options + } export default config; - -// Full theme configs here: https://nextra.site/docs/docs-theme/theme-configuration -