import { ActionProvider, AgentKit, EvmWalletProvider } from '@coinbase/agentkit'; import { z } from 'zod'; import { BriefError, createBlockchainIqBriefCall } from './brief-core.js'; export { BriefError, BRIEF_URL, NETWORK, USDC, AMOUNT, quoteBrief, validateChallenge, validateAuthorization } from './brief-core.js'; const EmptyInput = z.object({}).strict(); export const ACTION_NAME = 'blockchainiq_market_brief'; /** * Native AgentKit ActionProvider, bound to the engine's EVM wallet provider. * getActions is an intentional public-API override: AgentKit 0.10.4's optional * CreateAction decorator unconditionally emits a separate analytics POST. * This provider does not use that decorator, patch the SDK, or enable any other * wallet actions. The engine still performs its native supportsNetwork filter. */ export class BlockchainIqActionProvider extends ActionProvider { #wallet; #run; constructor({ expectedPayTo, fetchImpl = globalThis.fetch } = {}) { super('blockchainiq', []); this.#run = createBlockchainIqBriefCall({ expectedPayTo, fetchImpl, signerFactory: () => { if (!this.#wallet) throw new BriefError('WALLET_NOT_BOUND'); return { address: this.#wallet.getAddress(), signTypedData: input => this.#wallet.signTypedData(input), }; }, }); } supportsNetwork(network) { return network?.protocolFamily === 'evm' && network?.chainId === '8453'; } getActions(walletProvider) { if (!(walletProvider instanceof EvmWalletProvider)) { throw new BriefError('EVM_WALLET_PROVIDER_REQUIRED'); } let supported = false; try { supported = this.supportsNetwork(walletProvider.getNetwork()); } catch { throw new BriefError('WALLET_NETWORK_UNAVAILABLE'); } if (!supported) throw new BriefError('BASE_WALLET_REQUIRED'); if (this.#wallet && this.#wallet !== walletProvider) { throw new BriefError('WALLET_REBIND_FORBIDDEN'); } this.#wallet = walletProvider; return [{ name: ACTION_NAME, description: 'Buy one Blockchain IQ market brief for exactly 0.01 USDC on Base through x402. Single-use per provider; returns JSON and settlement proof. No action arguments. Wallet and expected recipient are application configuration.', schema: EmptyInput, invoke: async args => { try { if (!EmptyInput.safeParse(args).success) throw new Error(); } catch { throw new BriefError('INVALID_ACTION_INPUT'); } return this.#run(); }, }]; } } export function blockchainIqActionProvider(options) { return new BlockchainIqActionProvider(options); } /** All configuration is application-owned; never pass any of it as model input. */ export async function createBlockchainIqAgentKit({ walletProvider, expectedPayTo, fetchImpl = globalThis.fetch } = {}) { if (!(walletProvider instanceof EvmWalletProvider)) { throw new BriefError('EVM_WALLET_PROVIDER_REQUIRED'); } const provider = blockchainIqActionProvider({ expectedPayTo, fetchImpl }); let network; try { network = walletProvider.getNetwork(); } catch { throw new BriefError('WALLET_NETWORK_UNAVAILABLE'); } if (!provider.supportsNetwork(network)) { throw new BriefError('BASE_WALLET_REQUIRED'); } // Explicit wallet and exact provider prevent AgentKit's default CDP or // broad wallet actions from being selected. return AgentKit.from({ walletProvider, actionProviders: [provider] }); }