Here is a guide for interacting with AI service endpoints to create an agent.
Prerequisites
Before you begin, configure your .env
file. Here is an example:
Copy # Network Configuration
PROVIDER_RPC=your_provider_rpc_url_here
# Wallet Configuration
AGENT_PRIVATE_KEY=your_private_key_here
AGENT_ADDRESS=your_wallet_address_here
# IPFS CONFIG for managing budgets
LIGHTHOUSE_API_KEY=
IPFS_PROJECT_ID=
IPFS_PROJECT_SECRET=
# Project Configuration
PROJECT_ID=
# Resource Budget (Defaults to 5)
DEFAULT_RESOURCE_BUDGET=5
Resource Budget Management
Before using any service endpoints, you must configure and manage your resource budget. The following functions from src/services/Skynet.ts
handle budget management:
Create initial budget
Copy const createBudget = async (appName: string, subnetId: string) => {
const skyNode = await getSkyNode();
if (!process.env.PROJECT_ID) {
return {
success: false,
nftId: "",
appId: 0
}
}
const contractApp = {
nftID: process.env.PROJECT_ID!,
appID: "",
appName: `${appName}`,
appPath: Buffer.from(STORAGE_TYPE.LIGHTHOUSE + '/').toString('hex'),
modPath: Buffer.from(STORAGE_TYPE.LIGHTHOUSE + '/').toString('hex'),
appSubnetConfig: [{
resourceType: [1],
resourceCount: [1],
multiplier: [1]
}],
subnetList: [subnetId],
cidLock: false
}
const subscriptionParam = {
licenseAddress: "0x0000000000000000000000000000000000000000",
supportAddress: "0x3C904a5f23f868f309a6DB2a428529F33848f517",
platformAddress: "0xBC6200490F4bFC9092eA2987Ddb1Df478997e0cd",
referralAddress: "0x0000000000000000000000000000000000000000",
createTime: 0
}
const createTimeResp = await skyNode.dripRateManager.getSubscriptionParam(process.env.PROJECT_ID!);
if (createTimeResp?.success && createTimeResp.data.createTime > 0) {
subscriptionParam.createTime = createTimeResp.data.createTime;
}
const createAppResponse = await skyNode.appManager.createApp(
contractApp,
subscriptionParam,
{
licenseFactor: 0,
supportFactor: 0,
platformFactor: 0,
referralFactor: 0,
discountFactor: 0,
referralExpiryDuration: 0,
createTime: 0,
daoRate: 0
},
[etherToWei(Number(process.env.DEFAULT_RESOURCE_BUDGET!), 18).toString()],
{},
{
modAttribVar: {},
contractParam: {},
loggerURL: "https://appsender.skynet.io/api/appStatus"
},
async (status) => {
if (status === CRUD_APP_STAGE.CREATE_SUCCESSFUL) {
console.log("status", status);
}
},
{ fetchAppList: true, fetchSubscriptionParam: true, fetchBalanceForSubscription: true, getDeploymentStatus: false }
);
return createAppResponse;
}
Verify and Auto-top up Budget
Copy const verifyBudget = async (appName: string, subnetId: string) => {
const appList = await fetchApps();
if (!appList) return false;
const subnetList = appList.flatMap(app => app.subnetList);
if (!subnetList.includes(subnetId)) {
await createBudget(appName, subnetId);
return true;
};
const verifyBudgetResponse = await getSubnetBalance(subnetId);
if (verifyBudgetResponse && Number(verifyBudgetResponse) < (Number(process.env.DEFAULT_RESOURCE_BUDGET!) * 0.5)) {
await addBudget(subnetId);
return true;
}
return true;
}
Add More Budget
Copy const addBudget = async (subnetId: string) => {
const skyNode = await getSkyNode();
const valueInWei = ethers.utils.parseEther(process.env.DEFAULT_RESOURCE_BUDGET!);
const addbalanceRespose = await skyNode.contractService.SkynetWrapper.addBalanceByBuyingXCT(
process.env.PROJECT_ID!,
[subnetId],
[valueInWei.toString()],
{ value: valueInWei }
);
return addbalanceRespose;
}
Required environment variables for budget management:
Copy PROVIDER_RPC= # Your RPC provider URL
AGENT_PRIVATE_KEY= # Your wallet private key
PROJECT_ID= # Your project NFT ID
DEFAULT_RESOURCE_BUDGET= # Default budget amount in ETH
Example usage:
Copy // Before making API calls, verify budget
await verifyBudget("MyApp", "4");
Ensure sufficient budget is maintained to use the service endpoints
The system automatically tops up when balance falls below 50% of DEFAULT_RESOURCE_BUDGET
Initial budget creation is required for first-time subnet usage
Budget management functions require proper wallet configuration with sufficient funds
SDK Initialization
Copy import SkyMainNodeJS from '@decloudlabs/skynet/lib/services/SkyMainNodeJS';
const initializeSkyNodeCrypto = async (): Promise<SkyMainNodeJS> => {
if (!global.initializedAppCrypto) {
const envConfig = {
JRPC_PROVIDER: process.env.PROVIDER_RPC!,
WALLET_PRIVATE_KEY: process.env.AGENT_PRIVATE_KEY!,
STORAGE_API: {}
};
global.initializedAppCrypto = new SkyMainNodeJS(envConfig);
await global.initializedAppCrypto.init(true);
}
return global.initializedAppCrypto;
};
Authentication
All endpoints require these parameters:
Copy {
"userAuthPayload": {
"userAddress": "0xYourWalletAddress",
"signature": "<unique-signature>",
"message": "<timestamp>"
},
"prompt": "Your prompt",
"nftId": "YourNFTId"
}
userAuthPayload
Get user auth payload using await skynode.appManager.getUrsulaAuth()
Service Endpoints
1. StackAI (Ethereum Explorer)
POST https://stackaiservice.metalturtle.xyz/natural-request
Copy {
"userAuthPayload": { ... },
"nftId": "YourNFTId",
"prompt": "Deploy alethio/ethereum-lite-explorer"
}
2. RunPod (ML/AI Pods)
POST https://runpodservice-n694.stackos.io/natural-request
Copy {
"userAuthPayload": { ... },
"nftId": "YourNFTId",
"prompt": "Create a new pod with config X"
}
3. Claude (AI Text)
POST https://claudeservice-n694.stackos.io/claude-3-5-sonnet-20241022/natural-request
Copy {
"userAuthPayload": { ... },
"nftId": "YourNFTId",
"messages": [
{
"role": "user",
"content": "Your prompt"
}
]
}
4. OpenAI (AI Text)
POST https://openapiservice-n244.stackos.io/natural-request/gpt-4-turbo/focused
Copy {
"userAuthPayload": { ... },
"nftId": "YourNFTId",
"prompt": "Your prompt"
}
5. IPFS (File Storage)
POST https://lightservice-n694.stackos.io/natural-request
Content-Type : multipart/form-data
Copy {
"userAuthPayload": { ... },
"nftId": "YourNFTId",
"prompt": "Upload files",
"files": [/* File array */]
}
Example Implementation
This example demonstrates how to initialize the SDK and interact with the various service endpoints.
Copy import { AIServiceClient } from './services/AIServiceClient';
import express, { Request, Response } from 'express';
import dotenv from 'dotenv';
import cors from 'cors';
import bodyParser from 'body-parser';
// Load environment variables
dotenv.config();
const app = express();
const port = process.env.PORT || 3000;
// Middleware
app.use(cors()); // Add CORS middleware
app.use(bodyParser.json());
// Initialize AI client outside of route handler
const aiClient = new AIServiceClient();
// Initialize AI client when server starts
async function initializeAIClient() {
await aiClient.initialize();
console.log('AI Client initialized');
}
app.post('/api/generate-image', async (req, res) => {
try {
const { prompt } = req.body;
if (!prompt) {
return res.status(400).json({
success: false,
error: 'Prompt is required'
});
}
const imageResult = await aiClient.generateAndStoreImage(prompt);
if (imageResult.success) {
res.json(imageResult);
} else {
res.status(500).json(imageResult);
}
} catch (error) {
res.status(500).json({
success: false,
error: 'Internal server error'
});
}
});
// Start server
app.listen(port, async () => {
await initializeAIClient();
console.log(`Server running on port ${port}`);
});
Last updated 4 months ago