@onchainfi/uplink
v2.2.0
Published
Access Point to the Onchain Aggregator - JavaScript/TypeScript SDK
Readme
Onchain Uplink
Quickstart
1. Install
npm install @onchainfi/uplink2. Get API Key
Visit onchain.fi/get-api-key
3. Make a Payment
import { Uplink } from '@onchainfi/uplink';
const uplink = new Uplink({
apiKey: process.env.ONCHAIN_API_KEY!,
privateKey: process.env.UPLINK_PRIVATE_KEY!,
network: 'base', // or 'solana'
createAtaFeeAcceptance: true,
minimumCrosschainFeeAcceptance: true,
});
const txHash = await uplink.pay({
to: '0xRecipient...',
amount: '$10'
});
console.log(`Paid! TX: ${txHash}`);That's it! Same-chain payments on Base and Solana.
📚 Examples
New to Uplink? Check out our comprehensive examples:
- 🎯 Client-Side Examples - AI agents, bots, CLI tools (5 examples)
- 🚀 Server-Side Examples - APIs, backend services (5 examples)
Both include detailed READMEs with patterns, best practices, and real-world use cases.
Installation
npm install @onchainfi/uplink
# or
yarn add @onchainfi/uplink
# or
pnpm add @onchainfi/uplinkFull Example
import { Uplink } from '@onchainfi/uplink';
// Initialize
const uplink = new Uplink({
apiKey: process.env.ONCHAIN_API_KEY!,
privateKey: process.env.UPLINK_PRIVATE_KEY!,
network: 'base',
createAtaFeeAcceptance: true,
minimumCrosschainFeeAcceptance: true,
});
// Make a payment
const txHash = await uplink.pay({
to: '0xRecipient...',
amount: '$10.50'
});
console.log(`Payment sent: ${txHash}`);Two Modes
Mode A: SDK Signs (Convenience)
SDK handles signing with your private key:
const uplink = new Uplink({
apiKey: process.env.ONCHAIN_API_KEY!,
privateKey: process.env.UPLINK_PRIVATE_KEY!,
createAtaFeeAcceptance: true,
minimumCrosschainFeeAcceptance: true,
});
const txHash = await uplink.pay({
to: '0xRecipient...',
amount: '$10'
});Mode B: Pre-Signed (Advanced/Secure)
You sign externally (hardware wallet, custom signer, etc.):
const uplink = new Uplink({
apiKey: process.env.ONCHAIN_API_KEY!,
createAtaFeeAcceptance: true,
minimumCrosschainFeeAcceptance: true,
});
// Sign with your external signer (hardware wallet, etc.)
// For Base (EVM) - Complete EIP-712 signing:
import { ethers } from 'ethers';
const wallet = new ethers.Wallet(privateKey); // Or hardware wallet
// EIP-712 signature for USDC Transfer with Authorization
const domain = {
name: 'USD Coin',
version: '2',
chainId: 8453, // Base
verifyingContract: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // USDC on Base
};
const types = {
TransferWithAuthorization: [
{ name: 'from', type: 'address' },
{ name: 'to', type: 'address' },
{ name: 'value', type: 'uint256' },
{ name: 'validAfter', type: 'uint256' },
{ name: 'validBefore', type: 'uint256' },
{ name: 'nonce', type: 'bytes32' },
],
};
const nonce = '0x' + Array.from(crypto.getRandomValues(new Uint8Array(32)))
.map(b => b.toString(16).padStart(2, '0'))
.join('');
const value = {
from: wallet.address,
to: '0xRecipient...',
value: BigInt(10_000_000), // 10 USDC (6 decimals)
validAfter: BigInt(0),
validBefore: BigInt(Math.floor(Date.now() / 1000) + 3600), // 1 hour
nonce,
};
const signature = await wallet.signTypedData(domain, types, value);
// Create x402 payment header
const paymentHeader = Buffer.from(JSON.stringify({
x402Version: 1,
scheme: 'exact',
network: 'base',
payload: {
signature,
authorization: {
from: wallet.address,
to: value.to,
value: value.value.toString(),
validAfter: value.validAfter.toString(),
validBefore: value.validBefore.toString(),
nonce,
},
},
})).toString('base64');
// Pass pre-signed header to Uplink
const txHash = await uplink.pay({
to: '0xRecipient...',
amount: '$10',
paymentHeader
});Amount Formats
All these work:
await uplink.pay({ to: '0x...', amount: '$10' }); // Dollar sign
await uplink.pay({ to: '0x...', amount: '10.50' }); // Plain number
await uplink.pay({ to: '0x...', amount: '10 USDC' }); // With tokenAdvanced Features
Idempotency (Safe Retries)
const txHash = await uplink.pay({
to: '0x...',
amount: '$10',
idempotencyKey: 'unique-payment-id-123'
});
// Retry safe - same key returns same tx_hash
const txHash2 = await uplink.pay({
to: '0x...',
amount: '$10',
idempotencyKey: 'unique-payment-id-123'
});
// txHash === txHash2Metadata Tracking
const txHash = await uplink.pay({
to: '0x...',
amount: '$10',
metadata: {
agent_id: 'gpt-4-assistant',
task_id: 'abc-123',
purpose: 'API credits'
}
});Routing Priority
// Optimize for speed
await uplink.pay({ to: '0x...', amount: '$10', priority: 'speed' });
// Optimize for cost
await uplink.pay({ to: '0x...', amount: '$10', priority: 'cost' });
// Optimize for reliability
await uplink.pay({ to: '0x...', amount: '$10', priority: 'reliability' });
// Balanced (default)
await uplink.pay({ to: '0x...', amount: '$10', priority: 'balanced' });Error Handling
import {
SamechainClient,
PaymentError,
AuthenticationError,
NetworkError
} from '@onchainfi/uplink';
try {
const txHash = await uplink.pay({ to: '0x...', amount: '$10' });
} catch (error) {
if (error instanceof AuthenticationError) {
console.error('Invalid API key');
} else if (error instanceof PaymentError) {
console.error(`Payment failed: ${error.reason}`);
} else if (error instanceof NetworkError) {
console.error('Network request failed');
}
}Configuration
const uplink = new Uplink({
apiKey: 'onchain_xxx',
privateKey: '0x...',
network: 'base', // Default: 'base'
apiUrl: 'https://api.onchain.fi', // Default: 'https://api.onchain.fi' (production)
maxRetries: 3, // Default: 3
retryDelay: 1.0, // Default: 1.0 (seconds)
timeout: 120.0, // Default: 120.0 (seconds)
solanaRpcUrl: 'https://api.mainnet-beta.solana.com', // Default: Solana mainnet RPC
createAtaFeeAcceptance: true, // Required: Acknowledge ATA fees
minimumCrosschainFeeAcceptance: true, // Required: Acknowledge cross-chain minimums
});Environment Configuration
Production (Default):
const uplink = new Uplink({
apiKey: process.env.ONCHAIN_API_KEY!,
privateKey: process.env.UPLINK_PRIVATE_KEY!,
createAtaFeeAcceptance: true,
minimumCrosschainFeeAcceptance: true,
// Uses production API: https://api.onchain.fi
});Staging/Testing:
const uplink = new Uplink({
apiKey: process.env.ONCHAIN_API_KEY!,
privateKey: process.env.UPLINK_PRIVATE_KEY!,
apiUrl: 'https://staging.onchain.fi', // Override for testing
createAtaFeeAcceptance: true,
minimumCrosschainFeeAcceptance: true,
});Or via environment variable:
export UPLINK_API_URL=https://staging.onchain.fiSecurity Best Practices
✅ DO: Use Environment Variables
import { Uplink } from '@onchainfi/uplink';
const uplink = new Uplink({
apiKey: process.env.ONCHAIN_API_KEY!,
privateKey: process.env.UPLINK_PRIVATE_KEY!,
createAtaFeeAcceptance: true,
minimumCrosschainFeeAcceptance: true,
});❌ DON'T: Hardcode Keys
// BAD - Will trigger security warning
const uplink = new Uplink({
apiKey: 'onchain_abc123...',
privateKey: '0x1234567...'
});Getting API Keys
- Onchain API Key: Visit onchain.fi/get-api-key
- Private Key: Use your wallet's export function (store securely!)
Requirements
- Node.js >= 18.0.0 (for native fetch)
- TypeScript (optional, but recommended)
License
AGPL-3.0
Links
- Documentation
- Examples - Client-side & server-side examples
- GitHub
- Support
