Skip to main content

1. Install dependencies

npm install @solana/web3.js x402-fetch dotenv @scure/base

2. Load your keypair

import { Keypair } from '@solana/web3.js';
import { Buffer } from 'node:buffer';
import { wrapFetchWithPayment } from 'x402-fetch';
import { base58 } from '@scure/base';
import dotenv from 'dotenv';

dotenv.config();

const secretKey = base58.decode(process.env.SOLANA_PRIVATE_KEY!);
const keypair = Keypair.fromSecretKey(secretKey);

3. Build a signer for x402

const fetchWithPayment = wrapFetchWithPayment(fetch, {
  async signMessage(message: string) {
    const invoice = Buffer.from(message, 'base64');
    const signature = Buffer.from(keypair.sign(invoice)).toString('base64');
    return signature;
  },
});

4. Trigger Horizon extraction

const baseUrl = process.env.HORIZON_BASE_URL ?? 'https://api.horizon.new/v1';

const response = await fetchWithPayment(`${baseUrl}/extract/website`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    sourceUrl: 'https://blog.horizon.new/product-update',
    metadata: { collection: 'product-updates' },
  }),
});

const job = await response.json();
console.log(job.jobId);

5. Monitor status

const status = await fetchWithPayment(job.statusUrl).then((res) => res.json());

if (status.state === 'failed') {
  console.error(status.error);
}

Tips

  • Keep the Solana private key in a secure store and never commit it to source control.
  • Fund the wallet on the intended cluster (Devnet vs. Mainnet) before replaying invoices.
  • Use Solana’s sendAndConfirmTransaction if you need to move funds into the wallet automatically during provisioning.