TypeScript SDK for Dapinet UsagePayments V1.2 smart contract.
npm install @dapinet/sdk ethers- ✅ Full TypeScript types for V1.2 contract
- ✅ Request data encoding helpers (string, JSON, ABI, etc.)
- ✅ EIP-712 signature helpers for
settleWithSig - ✅ Gas estimation utilities
- ✅ Zero dependencies (peer dependency on ethers v6)
import { encodeRequestData, apiIdToBytes32 } from '@dapinet/sdk';
import { ethers } from 'ethers';
// Simple string (e.g., city name for weather API)
const requestData = encodeRequestData('Paris');
// JSON object (e.g., complex API parameters)
const requestData = encodeRequestData({
city: 'Paris',
lang: 'fr',
units: 'metric'
});
// ABI-encoded (e.g., typed parameters)
const requestData = encodeRequestData([
['string', 'string'], // types
['BTC', 'USD'] // values
], { format: 'abi' });import { Contract, Wallet } from 'ethers';
import { encodeRequestData, apiIdToBytes32 } from '@dapinet/sdk';
const provider = new ethers.JsonRpcProvider('YOUR_RPC_URL');
const wallet = new Wallet('YOUR_PRIVATE_KEY', provider);
const contract = new Contract(CONTRACT_ADDRESS, ABI, wallet);
// Encode API ID
const apiId = apiIdToBytes32('weather-api');
// Encode request data
const requestData = encodeRequestData('Paris');
// Send request with payment
const tx = await contract.requestApiCall(apiId, requestData, {
value: ethers.parseEther('0.0001') // API price
});
await tx.wait();
console.log('Request sent:', tx.hash);import { signSettle, combineSignature, createDeadline } from '@dapinet/sdk';
import { Contract, Wallet } from 'ethers';
// Operator signs the settlement
const operatorWallet = new Wallet('OPERATOR_PRIVATE_KEY');
const deadline = createDeadline(300); // 5 minutes from now
const signature = await signSettle(operatorWallet, {
contractAddress: CONTRACT_ADDRESS,
chainId: 421614, // Arbitrum Sepolia
requestId: 1n,
responseData: JSON.stringify({ temp: 10.2, city: 'Paris' }),
nonce: 0n, // Get from contract: contract.operatorNonces(operatorAddress)
deadline,
});
// Relayer (anyone) submits the settlement
const relayerWallet = new Wallet('RELAYER_PRIVATE_KEY', provider);
const contract = new Contract(CONTRACT_ADDRESS, ABI, relayerWallet);
const signatureBytes = combineSignature(signature);
const responseDataBytes = ethers.toUtf8Bytes(JSON.stringify({ temp: 10.2, city: 'Paris' }));
const tx = await contract.settleWithSig(
signature.requestId,
responseDataBytes,
signature.deadline,
signatureBytes
);
await tx.wait();
console.log('Settled with signature:', tx.hash);Encode request data for API calls.
Parameters:
data: Data to encode (string, object, array, or hex)options: Optional encoding optionsformat: Encoding format ('string'|'json'|'abi'|'abi-packed'|'hex'|'urlencoded')
Returns: Encoded bytes as hex string
Examples:
// Simple string
encodeRequestData('Paris') // -> 0x5061726973
// JSON object
encodeRequestData({ city: 'Paris', lang: 'fr' })
// ABI-encoded parameters
encodeRequestData([['string', 'uint256'], ['BTC', 1000]], { format: 'abi' })
// URL-encoded query string
encodeRequestData({ q: 'Paris', lang: 'fr' }, { format: 'urlencoded' })
// -> "q=Paris&lang=fr"Decode request data from bytes.
Parameters:
bytes: Encoded bytes (hex string or Uint8Array)format: Expected format (default:'string')
Returns: Decoded data
Create an EIP-712 signature for settleWithSig.
Parameters:
wallet: Ethers wallet or signer (operator)params: Signature parameterscontractAddress: UsagePayments contract addresschainId: Chain ID (e.g., 421614 for Arbitrum Sepolia)requestId: Request ID (bigint)responseData: Response data (string, will be hashed)nonce: Current nonce for operator (bigint)deadline: Signature expiration timestamp (bigint)
Returns: Promise with { requestId, responseHash, nonce, deadline, v, r, s }
Combine v, r, s into a signature bytes.
Parameters:
sig: Signature components{ v, r, s }
Returns: Signature as bytes (0x-prefixed hex string)
Create a deadline timestamp.
Parameters:
durationSeconds: Duration in seconds (default: 300 = 5 minutes)
Returns: Deadline timestamp (bigint, seconds since epoch)
Convert API ID string to bytes32 hash.
Parameters:
apiId: API ID string (e.g.,'weather-api')
Returns: bytes32 hash (0x-prefixed hex string)
Estimate gas for requestApiCall.
Parameters:
requestDataSize: Size of request data in bytes
Returns: Estimated gas (bigint)
Format wei to ETH string / Parse ETH string to wei.
Best for: Simple parameters (city name, ticker symbol, etc.)
encodeRequestData('Paris')
encodeRequestData('BTC')Best for: Complex structured data
encodeRequestData({ city: 'Paris', lang: 'fr', units: 'metric' })Best for: Type-safe encoding with Solidity types
// Multiple parameters with types
encodeRequestData([
['string', 'string', 'uint256'], // types
['BTC', 'USD', 1000] // values
], { format: 'abi' })Best for: Gas-efficient encoding (no padding)
encodeRequestData([
['string', 'uint256'],
['BTC', 1000]
], { format: 'abi-packed' })Best for: REST API query parameters
encodeRequestData({ q: 'Paris', lang: 'fr' }, { format: 'urlencoded' })
// Result: "q=Paris&lang=fr"Best for: Pre-encoded binary data
encodeRequestData('0x1234abcd', { format: 'hex' })All TypeScript types are exported:
import {
RequestedEvent,
SettledEvent,
ResponseEvent,
SettledWithSigEvent,
RequestStatus,
Request,
ApiInfo,
RequestDataFormat,
EncodeOptions,
SettleSignature,
DapinetConfig
} from '@dapinet/sdk';import { ethers } from 'ethers';
import { encodeRequestData, apiIdToBytes32 } from '@dapinet/sdk';
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);
const contract = new ethers.Contract(CONTRACT_ADDRESS, ABI, wallet);
async function requestWeather(city: string) {
const apiId = apiIdToBytes32('weather-api');
const requestData = encodeRequestData(city);
const tx = await contract.requestApiCall(apiId, requestData, {
value: ethers.parseEther('0.0001')
});
const receipt = await tx.wait();
const event = receipt.logs.find(log => log.topics[0] === contract.interface.getEvent('Requested').topicHash);
const requestId = event.topics[1];
console.log(`Weather requested for ${city}, requestId: ${requestId}`);
return requestId;
}
await requestWeather('Paris');import { encodeRequestData, apiIdToBytes32 } from '@dapinet/sdk';
const apiId = apiIdToBytes32('crypto-price');
// JSON encoding for complex parameters
const requestData = encodeRequestData({
symbols: ['BTC', 'ETH', 'SOL'],
currency: 'USD',
includeChange: true
});
const tx = await contract.requestApiCall(apiId, requestData, {
value: ethers.parseEther('0.0005')
});import { signSettle, combineSignature, createDeadline } from '@dapinet/sdk';
// Operator service (off-chain)
class OperatorService {
async createSettlement(requestId: bigint, responseData: string) {
const nonce = await contract.operatorNonces(this.operatorAddress);
const deadline = createDeadline(300); // 5 min
const signature = await signSettle(this.operatorWallet, {
contractAddress: CONTRACT_ADDRESS,
chainId: 421614,
requestId,
responseData,
nonce,
deadline
});
// Send signature to relayer service
await this.relayerApi.post('/settle', {
requestId: signature.requestId.toString(),
responseData,
deadline: signature.deadline.toString(),
signature: combineSignature(signature)
});
}
}
// Relayer service (pays gas)
class RelayerService {
async settleBatch(settlements: Settlement[]) {
for (const s of settlements) {
const responseDataBytes = ethers.toUtf8Bytes(s.responseData);
const tx = await this.contract.settleWithSig(
s.requestId,
responseDataBytes,
s.deadline,
s.signature
);
await tx.wait();
console.log(`Settled request ${s.requestId}, tx: ${tx.hash}`);
}
}
}The full UsagePayments V1.2 ABI is available in the main contract repository:
/dapinet/contracts/out/UsagePaymentsV1_2.sol/UsagePaymentsV1_2.json
- Documentation:
/dapinet/contracts/ENCODING_GUIDE.md - Contract: Arbitrum Sepolia Explorer
- GitHub: https://github.com/dapinet/dapinet
Business Source License 1.1
Licensed under BSL 1.1 until 2029-01-01, then converts to MIT License.
- ✅ Free for: Personal use, education, internal commercial use
⚠️ Restricted: Cannot operate competing API marketplaces or networks- 🔓 Fully open: Converts to MIT License on 2029-01-01
See LICENSE for full terms.