This page documents the Gasolina REST API endpoints, request/response formats, and integration patterns. The Gasolina API is a lightweight service that verifies LayerZero messages and produces signatures for DVN contracts.
Base URL
After deploying Gasolina, your API will be available at:
- AWS:
https://<api-gateway-id>.execute-api.<region>.amazonaws.com
- GCP:
https://<service-name>-<hash>.a.run.app
Endpoints
Health Check
Verify that the Gasolina service is running.
Response:
Example:
curl https://your-gasolina-instance.com/
Get Signer Info
Retrieve the signer addresses registered with this Gasolina instance for a specific chain.
GET /signer-info?chainName={chainName}
Query Parameters:
| Parameter | Type | Required | Description |
|---|
chainName | string | Yes | The chain name (e.g., ethereum, bsc, arbitrum) |
Response:
{
signers: string[] // Array of signer addresses
}
Example:
curl "https://your-gasolina-instance.com/signer-info?chainName=ethereum"
Response:
{
"signers": [
"0x1234567890123456789012345678901234567890",
"0x0987654321098765432109876543210987654321"
]
}
The signer addresses returned here are what LayerZero uses when deploying the DVN contracts. These addresses must match the signers registered in the onchain DVN contract.
Request Signatures
Request signatures for a LayerZero message verification. This is the primary endpoint called by Essence to obtain verification signatures.
Request Body:
interface SignatureRequest {
lzMessageId: {
srcUAAddress: string; // Source OApp address
dstUAAddress: string; // Destination OApp address
srcChainId: string; // Source endpoint ID
dstChainId: string; // Destination endpoint ID
srcChainName: string; // Source chain name (e.g., "ethereum")
dstChainName: string; // Destination chain name (e.g., "bsc")
nonce: number; // Message nonce
};
srcTxHash: string; // Source transaction hash
expiration: number; // Signature expiration (Unix timestamp)
blockConfirmation: number; // Required block confirmations
ulnVersion: 'V2' | 'V302'; // ULN version
self?: string; // Optional: self reference for callbacks
skipVId?: boolean; // Optional: skip VID validation
}
Response:
interface SignatureResponse {
body: {
signatures: Array<{
signature: string; // Hex-encoded ECDSA signature
address: string; // Signer address (for verification)
}>;
};
}
Example Request:
curl -X POST https://your-gasolina-instance.com/ \
-H "Content-Type: application/json" \
-d '{
"lzMessageId": {
"srcUAAddress": "0x4fa745fccc04555f2afa8874cd23961636cdf982",
"dstUAAddress": "0xe9f183fc656656f1f17af1f2b0df79b8ff9ad8ed",
"srcChainId": "101",
"dstChainId": "102",
"srcChainName": "ethereum",
"dstChainName": "bsc",
"nonce": 190
},
"srcTxHash": "0x2c58710ed1a83e2fff10adb0eb2b70f9262df6937d45e65a6fca5f2a043e7332",
"expiration": 1701410857,
"blockConfirmation": 15,
"ulnVersion": "V2",
"skipVId": false
}'
Example Response:
{
"body": {
"signatures": [
{
"signature": "0x1234...abcd",
"address": "0x1234567890123456789012345678901234567890"
},
{
"signature": "0x5678...efgh",
"address": "0x0987654321098765432109876543210987654321"
}
]
}
}
Request Parameters Reference
lzMessageId Object
| Field | Type | Description |
|---|
srcUAAddress | string | The OApp address on the source chain |
dstUAAddress | string | The OApp address on the destination chain |
srcChainId | string | LayerZero endpoint ID of the source chain |
dstChainId | string | LayerZero endpoint ID of the destination chain |
srcChainName | string | Human-readable source chain name |
dstChainName | string | Human-readable destination chain name |
nonce | number | Sequential message nonce for this pathway |
Top-Level Fields
| Field | Type | Description |
|---|
srcTxHash | string | Transaction hash where PacketSent was emitted |
expiration | number | Unix timestamp after which signature is invalid |
blockConfirmation | number | Number of block confirmations required |
ulnVersion | string | "V2" for ULNv2, "V302" for ULN302 |
self | string? | Optional callback reference |
skipVId | boolean? | If true, skip VID validation (default: false) |
ULN Version Selection
| Version | Description | When to Use |
|---|
V2 | Legacy ULN version | For messages using ULNv2 Message Library |
V302 | Current ULN version | For messages using ULN302 Message Library |
Error Responses
HTTP Status Codes
| Status | Meaning | Common Causes |
|---|
200 | Success | Signatures generated successfully |
400 | Bad Request | Invalid request body or parameters |
404 | Not Found | Chain not supported or message not found |
500 | Internal Error | RPC failure or signing error |
Common Error Scenarios
Chain Not Supported
{
"error": "Chain not available",
"chainName": "unsupported-chain"
}
Solution: Ensure the chain is listed in your availableChainNames configuration and has RPC providers configured.
Message Not Found
{
"error": "PacketSent event not found",
"txHash": "0x..."
}
Solution: Verify the transaction hash is correct and the transaction has been mined. Check that your RPC providers are synced.
Block Confirmations Not Met
{
"error": "Insufficient block confirmations",
"required": 15,
"current": 5
}
Solution: Wait for more blocks to be mined before retrying the request.
RPC Provider Error
{
"error": "Failed to connect to RPC provider"
}
Solution: Check RPC provider configuration and ensure endpoints are accessible. Consider adding backup providers.
Testing Your API
Using the Test Script
Both gasolina-aws and gasolina-gcp include a test script:
# From repository root
ts-node scripts/testDeployment.ts -u <your-api-url> -e <environment>
Options:
| Flag | Description |
|---|
-u, --url | Your Gasolina API URL |
-e, --environment | mainnet or testnet |
Successful Response:
--- Sending request to https://your-api.com ---
Sample request: { lzMessageId: {...}, srcTxHash: '0x...', ... }
--- [200] Successful request ---
Response: {
signatures: [
{ signature: '<signature>', address: '<address>' },
{ signature: '<signature>', address: '<address>' }
]
}
Manual Testing
- Test health check:
curl https://your-gasolina-instance.com/
# Expected: HEALTHY
- Test signer info:
curl "https://your-gasolina-instance.com/signer-info?chainName=ethereum"
# Expected: { "signers": ["0x...", "0x..."] }
- Test with sample message:
# Create a test payload file
cat > test-payload.json << 'EOF'
{
"lzMessageId": {
"srcUAAddress": "0xc769361cce2a4a61572d59faf3b58065c6faac04",
"dstUAAddress": "0xc769361cce2a4a61572d59faf3b58065c6faac04",
"srcChainId": "40161",
"dstChainId": "40102",
"srcChainName": "sepolia",
"dstChainName": "bsc",
"nonce": 1
},
"srcTxHash": "0xc5171abb2c8601ff5062c27c12f32c609b89eb38876a2509a4cd6d5327c64564",
"expiration": 1701493303,
"blockConfirmation": 1,
"ulnVersion": "V302",
"skipVId": true
}
EOF
# Send test request
curl -X POST https://your-gasolina-instance.com/ \
-H "Content-Type: application/json" \
-d @test-payload.json
If you’ve configured extra context verification, Gasolina will call your custom API for additional validation.
interface ExtraContextRequest {
sentEvent: {
lzMessageId: {
pathwayId: {
srcEid: number;
dstEid: number;
sender: string;
receiver: string;
srcChainName: string;
dstChainName: string;
};
nonce: number;
ulnSendVersion: string;
};
guid: string;
message: string;
options: {
lzReceive?: {gas: string; value: string};
nativeDrop?: Array<{amount: string; receiver: string}>;
compose?: Array<{index: number; gas: string; value: string}>;
ordered?: boolean;
};
payload?: string;
sendLibrary?: string;
onChainEvent: {
chainName: string;
txHash: string;
blockHash: string;
blockNumber: number;
};
};
from: string;
}
Expected Response
Your API should return a boolean indicating whether the message should be signed:
Or to reject:
Rate Limiting Considerations
While Gasolina doesn’t implement rate limiting by default, consider these factors:
-
RPC Provider Limits: Your RPC providers may have rate limits that affect signature generation speed.
-
Cloud Provider Limits:
- AWS API Gateway has default throttling limits
- GCP Cloud Run has concurrency limits
-
Scaling:
- AWS ECS auto-scales based on CPU/memory
- GCP Cloud Run auto-scales based on request volume
Security Considerations
-
No Authentication by Default: The API is publicly accessible. Consider adding:
- IP allowlisting at the load balancer level
- API key authentication if needed
- VPC/private endpoints for internal access
-
Signer Key Security:
- Keys are never exposed via the API
- Only signatures are returned, not private key material
-
Request Validation:
- Gasolina independently verifies events via RPC
- Block confirmation requirements are enforced
- Invalid requests are rejected before signing