
Research
2025 Report: Destructive Malware in Open Source Packages
Destructive malware is rising across open source registries, using delays and kill switches to wipe code, break builds, and disrupt CI/CD.
@blockend/compass-sdk
Advanced tools
Compass SDK is a powerful cross-chain transaction SDK that provides a unified liquidity layer by aggregating multiple liquidity sources across blockchain networks. It seamlessly integrates DEXs (Decentralized Exchanges), Cross-chain Bridges, RFQ (Request for Quote) systems, and Intent Protocols into a single, reliable interface. This enables developers to easily implement cross-chain token swaps, transfers, and complex DeFi operations across EVM chains, Solana, and Cosmos ecosystems.
The SDK automatically optimizes routes for the best rates and lowest fees by splitting transactions across multiple liquidity sources, handling complex cross-chain operations, and managing transaction sequences. It provides real-time price quotes, gas estimations, and transaction status tracking while abstracting away the complexity of cross-chain interactions.
npm install @blockend/compass-sdk
# or
yarn add @blockend/compass-sdk
For browser applications, you'll need to install the required blockchain libraries and configure polyfills:
# Install the blockchain libraries you need
npm install ethers viem @solana/web3.js bitcoinjs-lib
# For Buffer polyfill (required for bitcoinjs-lib)
npm install buffer
If you're using Vite, add this to your vite.config.js:
import { defineConfig } from 'vite'
import { resolve } from 'path'
export default defineConfig({
define: {
global: 'globalThis',
},
resolve: {
alias: {
buffer: 'buffer',
},
},
optimizeDeps: {
include: ['buffer'],
},
})
If you're using Webpack, add this to your webpack.config.js:
const webpack = require('webpack');
module.exports = {
resolve: {
fallback: {
"buffer": require.resolve("buffer"),
"crypto": require.resolve("crypto-browserify"),
"stream": require.resolve("stream-browserify"),
"process": require.resolve("process/browser"),
}
},
plugins: [
new webpack.ProvidePlugin({
Buffer: ['buffer', 'Buffer'],
process: 'process/browser',
}),
],
};
In your React app's entry point (e.g., index.js or main.jsx), add:
import { Buffer } from 'buffer';
// Make Buffer available globally
window.Buffer = Buffer;
import { initializeSDK, getQuotes, executeTransaction, createTransaction, getNextTxn, checkStatus } from "@blockend/compass-sdk";
// Initialize the SDK with your API key
initializeSDK({
apiKey: "YOUR_API_KEY",
integratorId: "YOUR_INTEGRATOR_ID",
});
// Get quotes for a token swap
const quotes = await getQuotes({
fromChainId: "137",
fromAssetAddress: "0x...",
toChainId: "sol",
toAssetAddress: "...",
inputAmount: "1000000000000000000", // Amount in wei
inputAmountDisplay: "1.0", // Human readable amount
userWalletAddress: "0x...",
recipient: "0x...",
});
// Execute the transaction with the best quote
const result = await executeTransaction({
quote: quotes.data.quotes[0],
provider: ethersProvider, // For EVM chains
walletAdapter: solanaWallet, // For Solana
cosmosClient: cosmosClient, // For Cosmos
onStatusUpdate: (status, data) => {
console.log(`Transaction status: ${status}`, data);
},
});
// Check transaction status, poll the status until the status is "success" or "failed" or "partial-success". "in-progress" means the transaction is still being processed.
const status = await checkStatus({
routeId: transaction.routeId,
stepId: transaction.steps[0].id,
txnHash: result.hash,
});
See checkStatus example implementation using while loop below.
initializeSDK(config)Initialize the SDK with your credentials and configuration.
initializeSDK({
apiKey: string;
integratorId: string;
baseURL?: string;
enableCache?: boolean;
cacheTimeout:number;
});
To get config, use the getConfig() method.
const config = getConfig();
To update config, use the updateConfig() method. You can update one or more parameters mentioned in the Configuration Parameters section.
updateConfig({
apiKey: "YOUR_API_KEY",
});
apiKey (required)integratorId (required)errorHandler (optional)BlockendError object with properties:
message: Description of the errorcode: Error code (e.g., "CONFIGURATION_ERROR", "NETWORK_ERROR", "VALIDATION_ERROR")data: Additional error context (if available)initializeSDK({
apiKey: "YOUR_API_KEY",
integratorId: "YOUR_INTEGRATOR_ID",
errorHandler: (error) => {
console.error(`[Compass SDK Error] ${error.code}: ${error.message}`, error.data);
// Custom error handling logic (e.g., reporting to monitoring service)
},
});
baseURL (optional)https://api2.blockend.com/v1/v1)enableCache (optional)false if not specifiedcacheTimeout (optional)enableCache is truegetQuotesGets quotes for cross-chain token swaps or transfers by aggregating liquidity from multiple sources including DEXs, Bridges, RFQs, and Intent Protocols.
interface QuoteParams {
// Chain ID of the source blockchain (e.g., "ethereum", "solana", "bsc")
fromChainId: string;
// Token contract address on source chain (use native token address for chain's native currency)
fromAssetAddress: string;
// Chain ID of the destination blockchain
toChainId: string;
// Token contract address on destination chain
toAssetAddress: string;
// Amount in smallest unit (wei, lamports, etc.)
inputAmount: string;
// Human readable amount (e.g., "1.0" ETH)
inputAmountDisplay: string;
// Source wallet address that will initiate the transaction
userWalletAddress: string;
// Optional: Destination wallet address (defaults to userWalletAddress if not specified)
recipient?: string;
// Optional: Solana priority fee in lamports or predefined level ("LOW" | "MEDIUM" | "HIGH")
solanaPriorityFee?: number | PriorityLevel;
// Optional: Solana Jito MEV tip in lamports or predefined level
solanaJitoTip?: number | PriorityLevel;
// Optional: EVM priority fee in gwei or predefined level
evmPriorityFee?: number | PriorityLevel;
// Optional: Maximum allowed slippage in BPS (default: 50)
slippage?: number;
// Optional: Skip certain validation checks for faster response
skipChecks?: boolean;
// Optional: Comma-separated list of preferred liquidity sources
include?: string;
// Optional: Comma-separated list of liquidity sources to exclude
exclude?: string;
// Optional: Use recommended liquidity provider
recommendedProvider?: boolean;
// Optional: To get gasless (approval + swap) transaction quotes.
gasless?:boolean;
// Optional: To get gasless transaction for swaps, but approvals may or may not require gas.
gaslessSwap:boolean;
// Optional: To set fee in BPS
feeBps: number | string;
}
//Example implementation
const quotes = await getQuotes({
fromChainId: "137",
fromAssetAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
toChainId: "137",
toAssetAddress: "0xc2132d05d31c914a87c6611c10748aeb04b58e8f.",
inputAmountDisplay: "1.0",
userWalletAddress: "0x...",
recipient: "0x...",
});
// Example Response (shortened)
{
"status": "success",
"data": {
"quotes": [{
"routeId": "01J2WB1NY6MD3F25CJTTB01D8F",
"from": {
"chainId": "1",
"symbol": "ETH",
// ... other token details
},
"to": {
"chainId": "sol",
"symbol": "USDC",
// ... other token details
},
"outputAmountDisplay": "1459.244847",
"estimatedTimeInSeconds": 900
}]
}
}
View full quotes response example
createTransaction(params)Creates a transaction from a selected quote, preparing all necessary steps for the cross-chain transfer.
interface CreateTransactionParams {
// Route ID obtained from getQuotes response
routeId: string;
}
//Example implementation
const transaction = await createTransaction({
routeId: quotes.data.quotes[0].routeId,
});
// Example Response (shortened)
{
"status": "success",
"data": {
"routeId": "01J2WB1NY6MD3F25CJTTB01D8F",
"steps": [{
"stepId": "01J2WB1NY64MKVCM8FM994WMZV",
"stepType": "bridge",
"chainId": "1"
}]
}
}
View full createTransaction response example
getNextTxn(params)Retrieves the raw transaction data for the next pending step in the transaction sequence. The response format varies based on the blockchain network:
interface TransactionDataParams {
routeId: string; // Route ID from createTransaction
stepId: string; // Step ID from the transaction steps array
}
//Example implementation
const nextTxn = await getNextTxn({
routeId: transaction.routeId,
stepId: transaction.steps[0].id,
});
// Example Response (shortened)
{
"status": "success",
"data": {
"routeId": "01J2WB1NY6MD3F25CJTTB01D8F",
"stepId": "01J2WB1NY64MKVCM8FM994WMZV",
"networkType": "evm",
"txnData": {
"txnType": "on-chain" | "sign-typed" | "sign-untyped"
"txnEvm": {
"to": "0x...",
"value": "420000000000000000",
// ... other transaction details
}
}
}
}
The SDK supports multiple transaction types that are automatically handled based on the protocol and requirements:
On-chain Transactions (txnType: "on-chain"):
// Example response for on-chain transaction
{
"txnType": "on-chain",
"txnEvm": {
"from": "0x17e7c3DD600529F34eFA1310f00996709FfA8d5c",
"to": "0x1234567890abcdef1234567890abcdef12345678",
"value": "420000000000000000",
"data": "0x095ea7b3...",
"gasPrice": "30000000000",
"gasLimit": "250000"
}
}
// Execute using wagmi/viem
import { getWalletClient } from "wagmi";
const client = await getWalletClient();
const hash = await client.sendTransaction({
to: txnEvm.to as `0x${string}`,
data: txnEvm.data as `0x${string}`,
value: BigInt(txnEvm.value),
gas: BigInt(txnEvm.gasLimit),
gasPrice: BigInt(txnEvm.gasPrice),
});
// Execute using ethers.js
import { BrowserProvider } from "ethers";
const provider = new BrowserProvider(window.ethereum);
const signer = await provider.getSigner();
const transaction = await signer.sendTransaction({
from: txnEvm.from,
to: txnEvm.to,
data: txnEvm.data,
gasLimit: txnEvm.gasLimit,
gasPrice: txnEvm.gasPrice,
value: txnEvm.value,
});
const hash = transaction.hash;
EIP-712 Typed Data Signing (txnType: "sign-typed"):
// Example response for typed data signing
{
"txnType": "sign-typed",
"txnEvm": {
"domain": {
"name": "Permit2",
"version": "1",
"chainId": 1,
"verifyingContract": "0x000000000022D473030F116dDEE9F6B43aC78BA3"
},
"types": {
"PermitSingle": [
{ "name": "details", "type": "PermitDetails" },
{ "name": "spender", "type": "address" },
{ "name": "sigDeadline", "type": "uint256" }
],
"PermitDetails": [
{ "name": "token", "type": "address" },
{ "name": "amount", "type": "uint160" },
{ "name": "expiration", "type": "uint48" },
{ "name": "nonce", "type": "uint48" }
]
},
"message": {
"details": {
"token": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"amount": "1461501637330902918203684832716283019655932542975",
"expiration": "1747836789",
"nonce": "0"
},
"spender": "0x1234567890123456789012345678901234567890",
"sigDeadline": "1747836789"
},
"primaryType": "PermitSingle"
}
}
// Execute using wagmi/viem
import { getWalletClient } from "wagmi";
const client = await getWalletClient();
const signature = await client.signTypedData({
account, // userWalletAddress
domain: txnEvm.domain,
types: txnEvm.types,
primaryType: txnEvm.primaryType,
message: txnEvm.message,
});
// Execute using ethers.js
import { BrowserProvider } from "ethers";
const provider = new BrowserProvider(window.ethereum);
const signer = await provider.getSigner();
// Remove EIP712Domain from types before signing
delete txnEvm.types.EIP712Domain;
const signature = await signer.signTypedData(
txnEvm.domain,
{
[txnEvm.primaryType]: txnEvm.types[txnEvm.primaryType],
...txnEvm.types,
},
txnEvm.message
);
Untyped Message Signing (txnType: "sign-untyped"):
// Example response for untyped message signing
{
"txnType": "sign-untyped",
"txnEvm": {
"message": "0x1901c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f4fc3",
}
}
// Execute using wagmi/viem
import { getWalletClient } from "wagmi";
const client = await getWalletClient();
const signature = await client.request({
method: "personal_sign",
params: [txnEvm.message, account],
});
// Execute using ethers.js
import { BrowserProvider } from "ethers";
const provider = new BrowserProvider(window.ethereum);
const signer = await provider.getSigner();
const signature = await provider.send("personal_sign", [
txnEvm.message,
account,
]);
The transaction type is automatically determined based on the quote and protocol being used. The SDK handles all the necessary signing logic internally, including:
Send txnEvm or txnSol or txnCosmos to the appropriate wallet/provider based on the networkType and get the transaction hash to monitor the status of the transaction.
{
"status": "success",
"data": {
"routeId": "01J2WB1NY6MD3F25CJTTB01D8F",
"stepId": "01J2WB1NY64MKVCM8FM994WMZV",
"networkType": "evm",
"txnData": {
"txnEvm": {
"from": "0x17e7c3DD600529F34eFA1310f00996709FfA8d5c",
"to": "0x1234567890abcdef1234567890abcdef12345678",
"value": "420000000000000000",
"data": "0x095ea7b3...",
"gasPrice": "30000000000",
"gasLimit": "250000"
}
}
}
}
{
"status": "success",
"data": {
"routeId": "01J2WB1NY6MD3F25CJTTB01D8F",
"stepId": "01J2WB1NY64MKVCM8FM994WMZV",
"networkType": "sol",
"txnData": {
"txnSol": {
"data": "base64EncodedTransactionData...",
}
}
}
}
{
"status": "success",
"data": {
"routeId": "01J2WB1NY6MD3F25CJTTB01D8F",
"stepId": "01J2WB1NY64MKVCM8FM994WMZV",
"networkType": "cosmos",
"txnData": {
"txnCosmos": {
"data": "{"typeUrl":"/ibc.applications.trans"}",
"value": "0",
"gasLimit": "250000",
"gasPrice": "0.025",
}
}
}
}
View full getNextTxn response example
checkStatus(params)Monitors the status of a transaction step, providing detailed information about its progress.
interface StatusCheckParams {
// Route ID of the transaction
routeId: string;
// Step ID being checked
stepId: string;
// Transaction hash from the blockchain
txnHash: string;
}
//Example implementation
const status = await checkStatus({
routeId: transaction.routeId,
stepId: transaction.steps[0].id,
txnHash: result.hash,
});
// Example Response (shortened)
{
"status": "success",
"data": {
"status": "success",
"outputAmount": "1459244847",
"outputAmountDisplay": "1459.244847"
}
}
type TransactionStatus = "not-started" | "in-progress" | "success" | "failed";
See checkStatus example implementation using while loop below.
View full checkStatus response example
Here's a simpler example to poll the transaction status:
async function pollWithWhileLoop(routeId: string, stepId: string, txnHash: string) {
const POLLING_INTERVAL = 3000; // 3 seconds
const MAX_ATTEMPTS = 200; // Maximum number of attempts (10 minutes with 3s interval)
let attempts = 0;
while (attempts < MAX_ATTEMPTS) {
try {
const response = await checkStatus({ routeId, stepId, txnHash });
const status = response.data.status;
console.log(`Current status: ${status}`);
if (["success", "failed", "partial-success"].includes(status)) {
return response.data;
}
// Wait for the polling interval
await new Promise((resolve) => setTimeout(resolve, POLLING_INTERVAL));
attempts++;
} catch (error) {
console.error("Error checking status:", error);
throw error;
}
}
throw new Error("Polling timeout: Maximum attempts reached");
}
// Usage example:
try {
const result = await pollWithWhileLoop("your-route-id", "your-step-id", "your-transaction-hash");
console.log("Final result:", result);
} catch (error) {
console.error("Polling failed:", error);
}
pollTransactionStatus(params)Continuously monitors a transaction's status by polling at regular intervals until a final state is reached or timeout occurs. This method provides a convenient way to track cross-chain transactions through their entire lifecycle.
interface PollTransactionStatusParams {
// Route ID of the transaction
routeId: string;
// Step ID being monitored
stepId: string;
// Transaction hash from the blockchain
txnHash: string;
// Optional: Interval between status checks in milliseconds (default: 2000ms)
pollingIntervalMs?: number;
// Optional: Maximum time to poll before timing out in milliseconds (default: 600000ms / 10 minutes)
timeoutMs?: number;
// Optional: Callback function for real-time status updates
onStatusUpdate?: (status: TransactionStatus, data?: ExecuteTransactionResult) => void;
}
// Example usage:
const result = await pollTransactionStatus({
routeId: "your-route-id",
stepId: "your-step-id",
txnHash: "your-transaction-hash",
pollingIntervalMs: 3000, // Poll every 3 seconds, by default it's 2 seconds
timeoutMs: 300000, // Timeout after 5 minutes, by default it's 10 minutes
onStatusUpdate: (status, data) => {
console.log(`Transaction status updated: ${status}`);
if (data) {
console.log("Transaction data:", data);
}
},
});
// Example Response
{
"status": "success",
"data": {
"status": "success",
"outputAmount": "1459244847",
"outputAmountDisplay": "1459.244847",
"srcTxnHash": "0x...",
"dstTxnHash": "0x...",
"srcTxnUrl": "https://etherscan.io/tx/0x...",
"dstTxnUrl": "https://etherscan.io/tx/0x...",
"points": 100,
"warnings": [],
}
}
The method will continue polling until one of these conditions is met:
Status Types:
"not-started": Transaction has not been initiated"in-progress": Transaction is being processed"success": Transaction completed successfully"failed": Transaction failed"partial-success": Transaction partially succeeded (some steps completed)Error Handling:
timeoutMs is exceededBlockendError classBest Practices:
pollingIntervalMs based on chain block timestimeoutMs for your use caseonStatusUpdate callback for real-time UI updatesexecuteQuote(params)Executes a complete transaction flow based on a quote, handling all necessary steps including approvals, swaps, and bridges.
interface ExecuteTransactionParams {
quote: Quote;
provider?: Provider | WalletClient;
walletAdapter?: WalletAdapter;
cosmosClient?: SigningStargateClient | SigningCosmWasmClient;
solanaRpcUrl?: string;
onStatusUpdate?: (status: TransactionStatus, data?: ExecuteTransactionResult) => void;
onCreateTxComplete?: (tx: CreateTransactionResponse) => void;
onNextTxComplete?: (tx: TransactionDataResponse) => void;
onSignComplete?: (txDetail: { stepId: string; txHash: string }) => void;
}
interface ExecuteTransactionResult {
routeId: string;
status: TransactionStatus;
srcTxnHash?: string;
srcTxnUrl?: string;
destTxnHash?: string;
destTxnUrl?: string;
outputAmount: string;
outputToken: Token;
warnings?: string[];
points?: number;
}
// Example implementation
const result = await executeQuote({
quote: quotes.data.quotes[0],
provider: ethersProvider, // For EVM chains
walletAdapter: solanaWallet, // For Solana
cosmosClient: cosmosClient, // For Cosmos
onStatusUpdate: (status, data) => {
console.log(`Transaction status: ${status}`, data);
},
onCreateTxComplete: (tx) => {
console.log("Transaction created:", tx);
},
onNextTxComplete: (tx) => {
console.log("Next transaction data:", tx);
},
onSignComplete: (txDetail) => {
console.log("Transaction signed:", txDetail);
},
});
executeTransaction(params)Executes a single transaction step with the provided transaction data. This method is used internally by executeQuote but can also be used directly for more granular control over transaction execution.
interface ExecuteTransactionParams {
txDataResponse: TransactionDataResponse;
quote: Quote;
step: TransactionStep;
provider: BrowserProvider | WalletClient;
walletAdapter: WalletAdapter;
cosmosClient: SigningStargateClient | SigningCosmWasmClient;
solanaRpcUrl?: string;
}
const txnResponse = await getNextTxn({
routeId: quote.routeId,
stepId: step.stepId,
});
// Example implementation
const txHash = await executeTransaction({
txDataResponse,
quote,
step,
provider: ethersProvider,
walletAdapter: solanaWallet,
cosmosClient: cosmosClient,
solanaRpcUrl: "https://api.mainnet-beta.solana.com",
});
The method handles different transaction types based on the network:
The method returns the transaction hash of the executed transaction, which can be used to monitor its status using checkStatus or pollTransactionStatus.
The SDK supports gasless transactions through two options in the QuoteParams:
interface QuoteParams {
// ... other params ...
// Optional: Get fully gasless transactions (both approval and swap)
gasless?: boolean;
// Optional: Get gasless swap transactions (approvals may still require gas)
gaslessSwap?: boolean;
}
Example of requesting a gasless quote:
const gaslessQuote = await getQuotes({
fromChainId: "137",
fromAssetAddress: "0x...",
toChainId: "1",
toAssetAddress: "0x...",
inputAmount: "1000000000000000000",
inputAmountDisplay: "1.0",
userWalletAddress: "0x...",
gasless: true, // Enable gasless(approval+swap) transactions
gaslessSwap: true, // Enable gasless atleast for swaps and approval may or not be gasless based on the tokens selected
});
Example response for a gasless quote:
{
"status": "success",
"data": {
"quotes": [{
"routeId": "01J2WB1NY6MD3F25CJTTB01D8F",
"from": {
"chainId": "137",
"symbol": "MATIC",
"address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
"decimals": 18,
"name": "Polygon",
"blockchain": "Polygon",
"isNative": true
},
"to": {
"chainId": "1",
"symbol": "USDC",
"address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"decimals": 6,
"name": "USD Coin",
"blockchain": "Ethereum"
},
"steps": [{
"stepId": "01J2WB1NY64MKVCM8FM994WMZV",
"stepType": "swap",
"protocolsUsed": ["uniswap-v3"],
"provider": "uniswap",
"gasless": true, // Indicates this step is gasless
"from": {
// Token details same as above
},
"to": {
// Token details same as above
},
"fee": [{
"name": "Protocol Fee",
"value": "0.3",
"token": "MATIC"
}],
"inputAmount": "1000000000000000000",
"outputAmount": "1459244847",
"estimatedTimeInSeconds": 300
}],
"outputAmountDisplay": "1.459244847",
"outputAmount": "1459244847",
"estimatedTimeInSeconds": 300,
"fee": [{
"name": "Protocol Fee",
"value": "0.3",
"token": "MATIC"
}],
"gasless": true // Indicates the entire route is gasless
}]
}
}
Example response for a gasless create transaction:
{
"status": "success",
"data": {
"routeId": "01J2WB1NY6MD3F25CJTTB01D8F",
"steps": [{
"stepId": "01J2WB1NY64MKVCM8FM994WMZV",
"stepType": "approval",
"protocolsUsed": ["permit2"],
"provider": "permit2",
"gasless": true,
"chainId": "137"
},
{
"stepId": "01J2WB1NY64MKVCM8FM994WMZW",
"stepType": "swap",
"protocolsUsed": ["uniswap-v3"],
"provider": "uniswap",
"gasless": true,
"chainId": "137"
}]
}
}
Example response for a gasless transaction step (swap):
{
"status": "success",
"data": {
"routeId": "01J2WB1NY6MD3F25CJTTB01D8F",
"stepId": "01J2WB1NY64MKVCM8FM994WMZW",
"networkType": "evm",
"txnData": {
"txnType": "sign-typed",
"txnEvm": {
"domain": {
"name": "Gasless Swap",
"version": "1",
"chainId": 137,
"verifyingContract": "0x9876543210987654321098765432109876543210"
},
"types": {
"MetaTransaction": [
{ "name": "from", "type": "address" },
{ "name": "to", "type": "address" },
{ "name": "value", "type": "uint256" },
{ "name": "nonce", "type": "uint256" },
{ "name": "deadline", "type": "uint256" }
]
},
"message": {
"from": "0x17e7c3DD600529F34eFA1310f00996709FfA8d5c",
"to": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
"value": "1000000000000000000",
"nonce": "1",
"deadline": "1747836789"
},
"primaryType": "MetaTransaction"
}
},
"gasless": true
}
}
Example code to execute a gasless transaction :
// wagami / viem
import { getWalletClient } from "wagmi";
import { config } from "./config";
const client = getWalletClient(config);
const signature = await client.signTypedData({
account, // userWalletAddress
domain,
types,
primaryType,
message,
});
// Ethers
import { BrowserProvider } from "ethers";
const provider = new BrowserProvider(window.ethereum);
//make sure the wallet is connected before executing this step
delete types.EIP712Domain;
const signer = await provider.getSigner();
const signature = await signer.signTypedData(
domain,
{
[primaryType]: types[primaryType],
...types,
},
message
);
getTokens(chainId?)Get a list of supported tokens, optionally filtered by chain ID.
interface TokensParams {
chainId?: string;
}
//Example implementation
const tokens = await getTokens();// to fetch all tokens from all chains
const tokens = await getTokens("1");// to fetch all tokens from chain 1
//Example response
{
"status": "success",
"data":{
"1":[
{
"networkType": "evm",
"address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
"chainId": "1",
"blockchain": "Ethereum",
"decimals": 18,
"name": "Ethereum",
"symbol": "ETH",
"image": "https://assets.coingecko.com/coins/images/279/standard/ethereum.png?1595348880",
"lastPrice": 2703.62,
"isEnabled": true,
"isFlagged": false,
"isNative": true,
"isPopular": true
},
//other coins on chain 1
]
}
}
getChains()Get a list of supported blockchain networks.
interface Chain {
id: string;
name: string;
networkType: "evm" | "sol" | "cosmos";
nativeCurrency: {
name: string;
symbol: string;
decimals: number;
};
blockExplorer: string;
rpcUrls: string[];
}
//Example implementation
const chains = await getChains(); // to fetch all chains
//Example response
{
"status": "success",
"data": [
{
"chainId": "sol",
"symbol": "sol",
"name": "Solana",
"networkType": "sol",
"image": "https://assets.coingecko.com/coins/images/4128/large/solana.png?1696504756",
"explorer": {
"address": "https://solscan.io/account/{address}",
"token": "https://solscan.io/token/{tokenAddress}",
"txn": "https://solscan.io/tx/{txnHash}"
},
"isPopular": true,
"tokenCount": 946,
"isEnabled": true
},
//other supported chains
]
}
The SDK uses a custom BlockendError class for error handling. All errors will be instances of this class and include:
message: Human-readable error messagecode: Error code for programmatic handlingdata: Additional error context (if available)onStatusUpdate callbackFAQs
Compass SDK for Blockend
We found that @blockend/compass-sdk demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
Destructive malware is rising across open source registries, using delays and kill switches to wipe code, break builds, and disrupt CI/CD.

Security News
Socket CTO Ahmad Nassri shares practical AI coding techniques, tools, and team workflows, plus what still feels noisy and why shipping remains human-led.

Research
/Security News
A five-month operation turned 27 npm packages into durable hosting for browser-run lures that mimic document-sharing portals and Microsoft sign-in, targeting 25 organizations across manufacturing, industrial automation, plastics, and healthcare for credential theft.