Monetize your API with x402

Recipes

Stake ETH From Fireblocks

Creates new validator keys and returns a staking transaction to deposit ETH to those validators. Then the staking transaction gets signed w Fireblocks API.

In this Recipe

  1. Provision validators
  2. Submit for Fireblocks signature
  3. Wait for Fireblocks signature
async function createValidators() {
  const url = '<https://api.figment.io/ethereum/validators>';
  const data = {
    network: 'hoodi',
    validators_count: 1,
    withdrawal_address: '0x8C025F5EdaBE788A7f14Db861420aaE12CDf979f',
    funding_address: '0x8C025F5EdaBE788A7f14Db861420aaE12CDf979f',
    fee_recipient_address: '0x8C025F5EdaBE788A7f14Db861420aaE12CDf979f',
    region: 'ca-central-1'
  };

try {
    const response = await axios.post(url, data, {
      headers: {
        'accept': 'application/json',
        'content-type': 'application/json',
        'x-api-key': process.env.FIGMENT_API_KEY
      }
    });

if (response.data && response.data.meta && response.data.meta.staking_transaction && response.data.meta.staking_transaction.contract_call_data) {
      return response.data.meta.staking_transaction.contract_call_data;
    } else {
      console.log('Contract Call Data not found in the response.');
      return null;
    }
  } catch (error) {
    console.error('Error:', error.response ? error.response.data : error);
    return null;
  }
}
async function signWithFireblocks(contractAddress, contractCallData) {
  console.log("Contract Call Data:", contractCallData);
  return fireblocksApiClient.createTransaction({
    operation: TransactionOperation.CONTRACT_CALL,
    assetId: process.env.FIREBLOCKS_ASSET_ID,
    source: {
      type: PeerType.VAULT_ACCOUNT,
      id: "1"
    },
    destination: {
      type: PeerType.ONE_TIME_ADDRESS,
      oneTimeAddress: {
        address: contractAddress
      }
    },
    note: "Contract Call Transaction",
    amount: "32",
    extraParameters: {
      contractCallData
    }
  }).then(res => {
    console.log(`✔ Submitted to Fireblocks for approval & signature. ID: ${res.id}`);
    return res;
  }).catch(e => {
    console.error(`Fireblocks API Error: ${e.message}`);
  });
}
async function waitForTxCompletion(fbTx) {
  let tx = fbTx;

while (tx.status !== TransactionStatus.COMPLETED) {
    if ([TransactionStatus.BLOCKED, TransactionStatus.FAILED, TransactionStatus.REJECTED, TransactionStatus.CANCELLED].includes(tx.status)) {
      throw new Error(`Exiting the operation due to error. Transaction status: ${tx.status}`);
    }

console.log("Transaction's status:", (await fireblocksApiClient.getTransactionById(fbTx.id)).status);
    await new Promise(resolve => setTimeout(resolve, 4000));
    tx = await fireblocksApiClient.getTransactionById(fbTx.id);
  }

return (await fireblocksApiClient.getTransactionById(fbTx.id));
}
async function processValidators() {
  const contractCallData = await createValidators();
  if (contractCallData) {
    const fbTx = await signWithFireblocks('0xA627f94a8F94E4713d38F52aC3a6377B0a111d47', contractCallData); // Use the actual contract address
    if (fbTx) {
      const fbRes = await waitForTxCompletion(fbTx);
      console.log(fbRes);
    }
  }
}

// Execute the combined function
processValidators();

Monetize your API with x402

Use Figment's x402 Facilitator to charge per API call

Sample Code

import 'dotenv/config';
import express from 'express';
import { paymentMiddleware, x402ResourceServer } from '@x402/express';
import { ExactSvmScheme } from '@x402/svm/exact/server';
import { HTTPFacilitatorClient } from '@x402/core/server';

const svmAddress = process.env.SVM_ADDRESS;
const facilitatorUrl = process.env.FACILITATOR_URL || 'http://localhost:4022';
const facilitatorApiKey = process.env.FACILITATOR_API_KEY;
const facilitatorOrgId = process.env.FACILITATOR_ORG_ID;
const network = process.env.SVM_NETWORK || 'solana-devnet';
const port = Number(process.env.PORT || 4021);

if (!svmAddress) {
  console.error('Set SVM_ADDRESS to the Solana wallet that should receive USDC payments.');
  process.exit(1);
}

if (!facilitatorApiKey || !facilitatorOrgId) {
  console.error('Set FACILITATOR_API_KEY (Kong bearer token) and FACILITATOR_ORG_ID (X-Figment-Org-Id) to authenticate against staking-accounts.');
  process.exit(1);
}

const authHeaders = {
  'x-api-key': facilitatorApiKey
};

const facilitatorClient = new HTTPFacilitatorClient({
  url: facilitatorUrl,
  createAuthHeaders: async () => ({
    verify: authHeaders,
    settle: authHeaders,
    supported: authHeaders,
  }),
});

const app = express();

app.use(
  paymentMiddleware(
    {
      'GET /data': {
        accepts: [
          {
            scheme: 'exact',
            price: '$0.001',
            network,
            payTo: svmAddress,
          },
        ],
        description: 'Sample paid data endpoint',
        mimeType: 'application/json',
      },
    },
    new x402ResourceServer(facilitatorClient).register(network, new ExactSvmScheme()),
  ),
);

app.get('/data', (_req, res) => {
  res.json({
    secret: 'gm — you paid 0.001 devnet USDC for this',
    timestamp: new Date().toISOString(),
  });
});

app.listen(port, () => {
  console.log(`sample data provider on http://localhost:${port}`);
  console.log(`  facilitator: ${facilitatorUrl}`);
  console.log(`  payTo:       ${svmAddress}`);
  console.log(`  network:     ${network}`);
});