@relai-fi/x402 0.5.27 → 0.5.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -94,6 +94,29 @@ function createManagementClient(config) {
94
94
  }
95
95
  return res.json();
96
96
  }
97
+ async function bridgeReq(method, path, x402Client, body) {
98
+ const res = await x402Client.fetch(`${base}${path}`, {
99
+ method,
100
+ headers: { ...headers, "Content-Type": "application/json" },
101
+ ...body !== void 0 ? { body: JSON.stringify(body) } : {}
102
+ });
103
+ if (!res.ok) {
104
+ const text = await res.text().catch(() => "");
105
+ let parsed = {};
106
+ try {
107
+ parsed = JSON.parse(text);
108
+ } catch {
109
+ }
110
+ if (res.status === 503 && parsed["reason"] === "insufficient_liquidity") {
111
+ const avail = parsed["available"];
112
+ throw new Error(
113
+ `Bridge temporarily unavailable \u2014 insufficient liquidity` + (avail != null ? ` (available: $${Number(avail).toFixed(2)} USDC)` : "")
114
+ );
115
+ }
116
+ throw new Error(`[relai-bridge] ${method} ${path} \u2192 ${res.status}: ${text}`);
117
+ }
118
+ return res.json();
119
+ }
97
120
  return {
98
121
  // ── APIs ──────────────────────────────────────────────────────────────
99
122
  createApi(input) {
@@ -138,6 +161,30 @@ function createManagementClient(config) {
138
161
  if (options.cursor) params.set("cursor", options.cursor);
139
162
  const qs = params.toString() ? `?${params}` : "";
140
163
  return req("GET", `/v1/apis/${apiId}/logs${qs}`);
164
+ },
165
+ // ── Bridge ──────────────────────────────────────────────────
166
+ getBridgeQuote(amount, from = "solana") {
167
+ const params = new URLSearchParams({ amount: String(amount), from });
168
+ return req("GET", `/v1/bridge/quote?${params}`);
169
+ },
170
+ getBridgeBalances() {
171
+ return req("GET", "/v1/bridge/balances");
172
+ },
173
+ async bridgeSolanaToSkale(amount, destinationWallet, x402Client) {
174
+ return bridgeReq(
175
+ "POST",
176
+ "/v1/bridge/solana-to-skale",
177
+ x402Client,
178
+ { amount, destinationWallet }
179
+ );
180
+ },
181
+ async bridgeSkaleToSolana(amount, destinationWallet, x402Client) {
182
+ return bridgeReq(
183
+ "POST",
184
+ "/v1/bridge/skale-to-solana",
185
+ x402Client,
186
+ { amount, destinationWallet }
187
+ );
141
188
  }
142
189
  };
143
190
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/management.ts"],"sourcesContent":["// src/management.ts\n// RelAI Management API client — create and manage monetised APIs programmatically.\n// Docs: https://relai.fi/documentation/management-api\n\nconst RELAI_API_BASE = 'https://api.relai.fi';\nconst BOOTSTRAP_URL = `${RELAI_API_BASE}/mcp/management/bootstrap/agent`;\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ManagementClientConfig {\n /** Service key (sk_live_...) for authenticating management API calls */\n serviceKey: string;\n /** Override base URL (default: https://api.relai.fi) */\n baseUrl?: string;\n}\n\nexport interface RelaiApi {\n apiId: string;\n name: string;\n description?: string;\n baseUrl: string;\n subdomain?: string | null;\n network: string;\n facilitator: string;\n x402Version: number;\n status: string;\n merchantWallet: string;\n solanaWallet?: string | null;\n /** EVM wallet for cross-chain payments. Only relevant when network is Solana. */\n evmCrossChainWallet?: string | null;\n websiteUrl?: string;\n logoUrl?: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface ApiEndpointInput {\n path: string;\n method: string;\n usdPrice: number;\n enabled?: boolean;\n}\n\nexport interface ApiEndpoint extends ApiEndpointInput {\n network: string;\n enabled: boolean;\n}\n\nexport interface CreateApiInput {\n name: string;\n baseUrl: string;\n merchantWallet: string;\n /** Solana wallet for cross-chain payments. Only relevant when network is EVM. */\n solanaWallet?: string;\n /** EVM wallet for cross-chain payments. Only relevant when network is Solana. */\n evmCrossChainWallet?: string;\n network: string;\n description?: string;\n websiteUrl?: string;\n logoUrl?: string;\n endpoints?: ApiEndpointInput[];\n}\n\nexport interface UpdateApiInput {\n name?: string;\n description?: string;\n baseUrl?: string;\n merchantWallet?: string;\n /** Solana wallet for cross-chain payments. Set to null to remove. */\n solanaWallet?: string | null;\n /** EVM wallet for cross-chain payments. Set to null to remove. */\n evmCrossChainWallet?: string | null;\n websiteUrl?: string;\n logoUrl?: string;\n}\n\nexport interface ApiStats {\n apiId: string;\n totalRequests: number;\n totalRevenue: number;\n currency: string;\n}\n\nexport interface ApiPayment {\n transaction: string;\n path: string;\n method: string;\n amount: number;\n currency: string;\n network: string;\n status: string;\n success: boolean;\n payer: string;\n createdAt: string;\n}\n\nexport interface ApiPaymentsResult {\n apiId: string;\n payments: ApiPayment[];\n nextCursor: string | null;\n}\n\nexport interface ApiLogItem {\n id: string;\n timestamp: string;\n method: string;\n path: string;\n status: string;\n cost: number;\n currency: string;\n duration: number;\n transaction: string;\n network: string;\n success: boolean;\n payer: string;\n}\n\nexport interface ApiLogsResult {\n items: ApiLogItem[];\n nextCursor: string | null;\n}\n\nexport interface AgentBootstrapResult {\n key: string;\n label: string;\n active: boolean;\n createdAt: string;\n}\n\n// ============================================================================\n// Agent bootstrap (autonomous key provisioning)\n// ============================================================================\n\n/**\n * Bootstrap a service key for a Solana agent.\n * Run once — store the returned key securely.\n *\n * @param keypair A Solana Keypair (from @solana/web3.js)\n * @param label Human-readable label for the key\n */\nexport async function bootstrapAgentKeySolana(\n keypair: { publicKey: { toBase58(): string }; secretKey: Uint8Array },\n label = 'agent',\n): Promise<AgentBootstrapResult> {\n const { sign } = await import('tweetnacl');\n\n const publicKey = keypair.publicKey.toBase58();\n\n // Step 1 — request challenge\n const challengeRes = await fetch(BOOTSTRAP_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ publicKey }),\n });\n if (!challengeRes.ok) throw new Error(`Challenge request failed: ${challengeRes.status}`);\n const { message } = await challengeRes.json() as { message: string };\n\n // Step 2 — sign\n const msgBytes = new TextEncoder().encode(message);\n const sigBytes = sign.detached(msgBytes, keypair.secretKey);\n const signature = Buffer.from(sigBytes).toString('base64');\n\n // Step 3 — get service key\n const keyRes = await fetch(BOOTSTRAP_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ publicKey, signature, message, label }),\n });\n if (!keyRes.ok) throw new Error(`Key provisioning failed: ${keyRes.status}`);\n return keyRes.json() as Promise<AgentBootstrapResult>;\n}\n\n/**\n * Bootstrap a service key for an EVM agent.\n * Run once — store the returned key securely.\n *\n * @param wallet An ethers.js Wallet or Signer with address + signMessage\n * @param label Human-readable label for the key\n */\nexport async function bootstrapAgentKeyEvm(\n wallet: { address: string; signMessage(message: string): Promise<string> },\n label = 'agent',\n): Promise<AgentBootstrapResult> {\n const publicKey = wallet.address;\n\n // Step 1 — request challenge\n const challengeRes = await fetch(BOOTSTRAP_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ publicKey }),\n });\n if (!challengeRes.ok) throw new Error(`Challenge request failed: ${challengeRes.status}`);\n const { message } = await challengeRes.json() as { message: string };\n\n // Step 2+3 — sign and get key\n const signature = await wallet.signMessage(message);\n const keyRes = await fetch(BOOTSTRAP_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ publicKey, signature, message, label }),\n });\n if (!keyRes.ok) throw new Error(`Key provisioning failed: ${keyRes.status}`);\n return keyRes.json() as Promise<AgentBootstrapResult>;\n}\n\n// ============================================================================\n// Management client\n// ============================================================================\n\nexport interface RelaiManagementClient {\n // APIs\n createApi(input: CreateApiInput): Promise<RelaiApi>;\n listApis(): Promise<RelaiApi[]>;\n getApi(apiId: string): Promise<RelaiApi>;\n updateApi(apiId: string, input: UpdateApiInput): Promise<RelaiApi>;\n deleteApi(apiId: string): Promise<{ success: boolean; apiId: string }>;\n\n // Pricing\n getPricing(apiId: string): Promise<{ apiId: string; endpoints: ApiEndpoint[] }>;\n setPricing(apiId: string, endpoints: ApiEndpointInput[]): Promise<{ success: boolean; apiId: string; updated: number }>;\n\n // Analytics\n getStats(apiId: string): Promise<ApiStats>;\n getPayments(apiId: string, options?: { limit?: number; from?: string; cursor?: string }): Promise<ApiPaymentsResult>;\n getLogs(apiId: string, options?: { limit?: number; from?: string; cursor?: string }): Promise<ApiLogsResult>;\n}\n\n/**\n * Create a RelAI Management API client.\n *\n * @example\n * ```typescript\n * import { createManagementClient } from '@relai-fi/x402/management';\n *\n * const mgmt = createManagementClient({ serviceKey: process.env.RELAI_SERVICE_KEY! });\n *\n * const api = await mgmt.createApi({\n * name: 'My ML API',\n * baseUrl: 'https://inference.example.com',\n * merchantWallet: '0xYourWallet',\n * network: 'base',\n * endpoints: [{ path: '/v1/predict', method: 'post', usdPrice: 0.05 }],\n * });\n * ```\n */\nexport function createManagementClient(config: ManagementClientConfig): RelaiManagementClient {\n const base = (config.baseUrl ?? RELAI_API_BASE).replace(/\\/$/, '');\n const headers = {\n 'X-Service-Key': config.serviceKey,\n 'Content-Type': 'application/json',\n };\n\n async function req<T>(method: string, path: string, body?: unknown): Promise<T> {\n const res = await fetch(`${base}${path}`, {\n method,\n headers,\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n });\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw new Error(`[relai-mgmt] ${method} ${path} → ${res.status}: ${text}`);\n }\n return res.json() as Promise<T>;\n }\n\n return {\n // ── APIs ──────────────────────────────────────────────────────────────\n\n createApi(input) {\n return req<RelaiApi>('POST', '/v1/apis', input);\n },\n\n async listApis() {\n const data = await req<{ apis: RelaiApi[] }>('GET', '/v1/apis');\n return data.apis;\n },\n\n getApi(apiId) {\n return req<RelaiApi>('GET', `/v1/apis/${apiId}`);\n },\n\n updateApi(apiId, input) {\n return req<RelaiApi>('PATCH', `/v1/apis/${apiId}`, input);\n },\n\n deleteApi(apiId) {\n return req<{ success: boolean; apiId: string }>('DELETE', `/v1/apis/${apiId}`);\n },\n\n // ── Pricing ──────────────────────────────────────────────────────────\n\n getPricing(apiId) {\n return req<{ apiId: string; endpoints: ApiEndpoint[] }>('GET', `/v1/apis/${apiId}/pricing`);\n },\n\n setPricing(apiId, endpoints) {\n return req<{ success: boolean; apiId: string; updated: number }>('PUT', `/v1/apis/${apiId}/pricing`, { endpoints });\n },\n\n // ── Analytics ────────────────────────────────────────────────────────\n\n getStats(apiId) {\n return req<ApiStats>('GET', `/v1/apis/${apiId}/stats`);\n },\n\n getPayments(apiId, options = {}) {\n const params = new URLSearchParams();\n if (options.limit) params.set('limit', String(options.limit));\n if (options.from) params.set('from', options.from);\n if (options.cursor) params.set('cursor', options.cursor);\n const qs = params.toString() ? `?${params}` : '';\n return req<ApiPaymentsResult>('GET', `/v1/apis/${apiId}/payments${qs}`);\n },\n\n getLogs(apiId, options = {}) {\n const params = new URLSearchParams();\n if (options.limit) params.set('limit', String(options.limit));\n if (options.from) params.set('from', options.from);\n if (options.cursor) params.set('cursor', options.cursor);\n const qs = params.toString() ? `?${params}` : '';\n return req<ApiLogsResult>('GET', `/v1/apis/${apiId}/logs${qs}`);\n },\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/management.ts"],"sourcesContent":["// src/management.ts\n// RelAI Management API client — create and manage monetised APIs programmatically.\n// Docs: https://relai.fi/documentation/management-api\n\nconst RELAI_API_BASE = 'https://api.relai.fi';\nconst BOOTSTRAP_URL = `${RELAI_API_BASE}/mcp/management/bootstrap/agent`;\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ManagementClientConfig {\n /** Service key (sk_live_...) for authenticating management API calls */\n serviceKey: string;\n /** Override base URL (default: https://api.relai.fi) */\n baseUrl?: string;\n}\n\nexport interface RelaiApi {\n apiId: string;\n name: string;\n description?: string;\n baseUrl: string;\n subdomain?: string | null;\n network: string;\n facilitator: string;\n x402Version: number;\n status: string;\n merchantWallet: string;\n solanaWallet?: string | null;\n /** EVM wallet for cross-chain payments. Only relevant when network is Solana. */\n evmCrossChainWallet?: string | null;\n websiteUrl?: string;\n logoUrl?: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface ApiEndpointInput {\n path: string;\n method: string;\n usdPrice: number;\n enabled?: boolean;\n}\n\nexport interface ApiEndpoint extends ApiEndpointInput {\n network: string;\n enabled: boolean;\n}\n\nexport interface CreateApiInput {\n name: string;\n baseUrl: string;\n merchantWallet: string;\n /** Solana wallet for cross-chain payments. Only relevant when network is EVM. */\n solanaWallet?: string;\n /** EVM wallet for cross-chain payments. Only relevant when network is Solana. */\n evmCrossChainWallet?: string;\n network: string;\n description?: string;\n websiteUrl?: string;\n logoUrl?: string;\n endpoints?: ApiEndpointInput[];\n}\n\nexport interface UpdateApiInput {\n name?: string;\n description?: string;\n baseUrl?: string;\n merchantWallet?: string;\n /** Solana wallet for cross-chain payments. Set to null to remove. */\n solanaWallet?: string | null;\n /** EVM wallet for cross-chain payments. Set to null to remove. */\n evmCrossChainWallet?: string | null;\n websiteUrl?: string;\n logoUrl?: string;\n}\n\nexport interface ApiStats {\n apiId: string;\n totalRequests: number;\n totalRevenue: number;\n currency: string;\n}\n\nexport interface ApiPayment {\n transaction: string;\n path: string;\n method: string;\n amount: number;\n currency: string;\n network: string;\n status: string;\n success: boolean;\n payer: string;\n createdAt: string;\n}\n\nexport interface ApiPaymentsResult {\n apiId: string;\n payments: ApiPayment[];\n nextCursor: string | null;\n}\n\nexport interface ApiLogItem {\n id: string;\n timestamp: string;\n method: string;\n path: string;\n status: string;\n cost: number;\n currency: string;\n duration: number;\n transaction: string;\n network: string;\n success: boolean;\n payer: string;\n}\n\nexport interface ApiLogsResult {\n items: ApiLogItem[];\n nextCursor: string | null;\n}\n\n// ── Bridge types ─────────────────────────────────────────────────────────────\n\nexport interface BridgeQuoteResult {\n inputAmount: number;\n outputAmount: number;\n fee: number;\n feeBps: number;\n inputUsd: number;\n outputUsd: number;\n direction: 'solana-to-skale' | 'skale-to-solana';\n from: string;\n to: string;\n}\n\nexport interface BridgeBalances {\n solana: { atomic: number; usd: number };\n skaleBase: { atomic: number; usd: number };\n base: { atomic: number; usd: number };\n}\n\nexport interface BridgeResult {\n success: boolean;\n direction: 'solana-to-skale' | 'skale-to-solana';\n destinationWallet: string;\n amountOut: number;\n amountOutUsd: number;\n txHash: string;\n explorerUrl: string;\n}\n\nexport interface AgentBootstrapResult {\n key: string;\n label: string;\n active: boolean;\n createdAt: string;\n}\n\n// ============================================================================\n// Agent bootstrap (autonomous key provisioning)\n// ============================================================================\n\n/**\n * Bootstrap a service key for a Solana agent.\n * Run once — store the returned key securely.\n *\n * @param keypair A Solana Keypair (from @solana/web3.js)\n * @param label Human-readable label for the key\n */\nexport async function bootstrapAgentKeySolana(\n keypair: { publicKey: { toBase58(): string }; secretKey: Uint8Array },\n label = 'agent',\n): Promise<AgentBootstrapResult> {\n const { sign } = await import('tweetnacl');\n\n const publicKey = keypair.publicKey.toBase58();\n\n // Step 1 — request challenge\n const challengeRes = await fetch(BOOTSTRAP_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ publicKey }),\n });\n if (!challengeRes.ok) throw new Error(`Challenge request failed: ${challengeRes.status}`);\n const { message } = await challengeRes.json() as { message: string };\n\n // Step 2 — sign\n const msgBytes = new TextEncoder().encode(message);\n const sigBytes = sign.detached(msgBytes, keypair.secretKey);\n const signature = Buffer.from(sigBytes).toString('base64');\n\n // Step 3 — get service key\n const keyRes = await fetch(BOOTSTRAP_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ publicKey, signature, message, label }),\n });\n if (!keyRes.ok) throw new Error(`Key provisioning failed: ${keyRes.status}`);\n return keyRes.json() as Promise<AgentBootstrapResult>;\n}\n\n/**\n * Bootstrap a service key for an EVM agent.\n * Run once — store the returned key securely.\n *\n * @param wallet An ethers.js Wallet or Signer with address + signMessage\n * @param label Human-readable label for the key\n */\nexport async function bootstrapAgentKeyEvm(\n wallet: { address: string; signMessage(message: string): Promise<string> },\n label = 'agent',\n): Promise<AgentBootstrapResult> {\n const publicKey = wallet.address;\n\n // Step 1 — request challenge\n const challengeRes = await fetch(BOOTSTRAP_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ publicKey }),\n });\n if (!challengeRes.ok) throw new Error(`Challenge request failed: ${challengeRes.status}`);\n const { message } = await challengeRes.json() as { message: string };\n\n // Step 2+3 — sign and get key\n const signature = await wallet.signMessage(message);\n const keyRes = await fetch(BOOTSTRAP_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ publicKey, signature, message, label }),\n });\n if (!keyRes.ok) throw new Error(`Key provisioning failed: ${keyRes.status}`);\n return keyRes.json() as Promise<AgentBootstrapResult>;\n}\n\n// ============================================================================\n// Management client\n// ============================================================================\n\nexport interface RelaiManagementClient {\n // APIs\n createApi(input: CreateApiInput): Promise<RelaiApi>;\n listApis(): Promise<RelaiApi[]>;\n getApi(apiId: string): Promise<RelaiApi>;\n updateApi(apiId: string, input: UpdateApiInput): Promise<RelaiApi>;\n deleteApi(apiId: string): Promise<{ success: boolean; apiId: string }>;\n\n // Pricing\n getPricing(apiId: string): Promise<{ apiId: string; endpoints: ApiEndpoint[] }>;\n setPricing(apiId: string, endpoints: ApiEndpointInput[]): Promise<{ success: boolean; apiId: string; updated: number }>;\n\n // Analytics\n getStats(apiId: string): Promise<ApiStats>;\n getPayments(apiId: string, options?: { limit?: number; from?: string; cursor?: string }): Promise<ApiPaymentsResult>;\n getLogs(apiId: string, options?: { limit?: number; from?: string; cursor?: string }): Promise<ApiLogsResult>;\n\n // Bridge\n /**\n * Get a bridge quote — fee and net output for a given USD amount.\n * @param amount Amount in USD (e.g. 10.0)\n * @param from Source network: 'solana' | 'skale-base' (default: 'solana')\n */\n getBridgeQuote(amount: number, from?: 'solana' | 'skale-base'): Promise<BridgeQuoteResult>;\n\n /**\n * Get current USDC liquidity on all bridge networks.\n * Use this before bridging to confirm availability.\n */\n getBridgeBalances(): Promise<BridgeBalances>;\n\n /**\n * Bridge USDC from Solana to SKALE Base via x402 payment.\n * This call returns HTTP 402 — pass a createX402Client instance to handle payment automatically.\n *\n * @param amount Amount in USD\n * @param destinationWallet EVM address on SKALE Base\n * @param x402Client A configured createX402Client instance for Solana\n */\n bridgeSolanaToSkale(\n amount: number,\n destinationWallet: string,\n x402Client: { fetch(url: string, init?: RequestInit): Promise<Response> },\n ): Promise<BridgeResult>;\n\n /**\n * Bridge USDC from SKALE Base to Solana via x402 payment.\n *\n * @param amount Amount in USD\n * @param destinationWallet Solana public key (base58)\n * @param x402Client A configured createX402Client instance for EVM/SKALE Base\n */\n bridgeSkaleToSolana(\n amount: number,\n destinationWallet: string,\n x402Client: { fetch(url: string, init?: RequestInit): Promise<Response> },\n ): Promise<BridgeResult>;\n}\n\n/**\n * Create a RelAI Management API client.\n *\n * @example\n * ```typescript\n * import { createManagementClient } from '@relai-fi/x402/management';\n *\n * const mgmt = createManagementClient({ serviceKey: process.env.RELAI_SERVICE_KEY! });\n *\n * const api = await mgmt.createApi({\n * name: 'My ML API',\n * baseUrl: 'https://inference.example.com',\n * merchantWallet: '0xYourWallet',\n * network: 'base',\n * endpoints: [{ path: '/v1/predict', method: 'post', usdPrice: 0.05 }],\n * });\n * ```\n */\nexport function createManagementClient(config: ManagementClientConfig): RelaiManagementClient {\n const base = (config.baseUrl ?? RELAI_API_BASE).replace(/\\/$/, '');\n const headers = {\n 'X-Service-Key': config.serviceKey,\n 'Content-Type': 'application/json',\n };\n\n async function req<T>(method: string, path: string, body?: unknown): Promise<T> {\n const res = await fetch(`${base}${path}`, {\n method,\n headers,\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n });\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw new Error(`[relai-mgmt] ${method} ${path} → ${res.status}: ${text}`);\n }\n return res.json() as Promise<T>;\n }\n\n async function bridgeReq<T>(\n method: string,\n path: string,\n x402Client: { fetch(url: string, init?: RequestInit): Promise<Response> },\n body?: unknown,\n ): Promise<T> {\n const res = await x402Client.fetch(`${base}${path}`, {\n method,\n headers: { ...headers, 'Content-Type': 'application/json' },\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n });\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n let parsed: Record<string, unknown> = {};\n try { parsed = JSON.parse(text); } catch { /* ignore */ }\n if (res.status === 503 && parsed['reason'] === 'insufficient_liquidity') {\n const avail = parsed['available'] as number | undefined;\n throw new Error(\n `Bridge temporarily unavailable — insufficient liquidity` +\n (avail != null ? ` (available: $${Number(avail).toFixed(2)} USDC)` : ''),\n );\n }\n throw new Error(`[relai-bridge] ${method} ${path} → ${res.status}: ${text}`);\n }\n return res.json() as Promise<T>;\n }\n\n return {\n // ── APIs ──────────────────────────────────────────────────────────────\n\n createApi(input) {\n return req<RelaiApi>('POST', '/v1/apis', input);\n },\n\n async listApis() {\n const data = await req<{ apis: RelaiApi[] }>('GET', '/v1/apis');\n return data.apis;\n },\n\n getApi(apiId) {\n return req<RelaiApi>('GET', `/v1/apis/${apiId}`);\n },\n\n updateApi(apiId, input) {\n return req<RelaiApi>('PATCH', `/v1/apis/${apiId}`, input);\n },\n\n deleteApi(apiId) {\n return req<{ success: boolean; apiId: string }>('DELETE', `/v1/apis/${apiId}`);\n },\n\n // ── Pricing ──────────────────────────────────────────────────────────\n\n getPricing(apiId) {\n return req<{ apiId: string; endpoints: ApiEndpoint[] }>('GET', `/v1/apis/${apiId}/pricing`);\n },\n\n setPricing(apiId, endpoints) {\n return req<{ success: boolean; apiId: string; updated: number }>('PUT', `/v1/apis/${apiId}/pricing`, { endpoints });\n },\n\n // ── Analytics ────────────────────────────────────────────────────────\n\n getStats(apiId) {\n return req<ApiStats>('GET', `/v1/apis/${apiId}/stats`);\n },\n\n getPayments(apiId, options = {}) {\n const params = new URLSearchParams();\n if (options.limit) params.set('limit', String(options.limit));\n if (options.from) params.set('from', options.from);\n if (options.cursor) params.set('cursor', options.cursor);\n const qs = params.toString() ? `?${params}` : '';\n return req<ApiPaymentsResult>('GET', `/v1/apis/${apiId}/payments${qs}`);\n },\n\n getLogs(apiId, options = {}) {\n const params = new URLSearchParams();\n if (options.limit) params.set('limit', String(options.limit));\n if (options.from) params.set('from', options.from);\n if (options.cursor) params.set('cursor', options.cursor);\n const qs = params.toString() ? `?${params}` : '';\n return req<ApiLogsResult>('GET', `/v1/apis/${apiId}/logs${qs}`);\n },\n\n // ── Bridge ──────────────────────────────────────────────────\n\n getBridgeQuote(amount, from = 'solana') {\n const params = new URLSearchParams({ amount: String(amount), from });\n return req<BridgeQuoteResult>('GET', `/v1/bridge/quote?${params}`);\n },\n\n getBridgeBalances() {\n return req<BridgeBalances>('GET', '/v1/bridge/balances');\n },\n\n async bridgeSolanaToSkale(amount, destinationWallet, x402Client) {\n return bridgeReq<BridgeResult>(\n 'POST',\n '/v1/bridge/solana-to-skale',\n x402Client,\n { amount, destinationWallet },\n );\n },\n\n async bridgeSkaleToSolana(amount, destinationWallet, x402Client) {\n return bridgeReq<BridgeResult>(\n 'POST',\n '/v1/bridge/skale-to-solana',\n x402Client,\n { amount, destinationWallet },\n );\n },\n };\n}\n"],"mappings":"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","names":[]}
@@ -100,6 +100,40 @@ interface ApiLogsResult {
100
100
  items: ApiLogItem[];
101
101
  nextCursor: string | null;
102
102
  }
103
+ interface BridgeQuoteResult {
104
+ inputAmount: number;
105
+ outputAmount: number;
106
+ fee: number;
107
+ feeBps: number;
108
+ inputUsd: number;
109
+ outputUsd: number;
110
+ direction: 'solana-to-skale' | 'skale-to-solana';
111
+ from: string;
112
+ to: string;
113
+ }
114
+ interface BridgeBalances {
115
+ solana: {
116
+ atomic: number;
117
+ usd: number;
118
+ };
119
+ skaleBase: {
120
+ atomic: number;
121
+ usd: number;
122
+ };
123
+ base: {
124
+ atomic: number;
125
+ usd: number;
126
+ };
127
+ }
128
+ interface BridgeResult {
129
+ success: boolean;
130
+ direction: 'solana-to-skale' | 'skale-to-solana';
131
+ destinationWallet: string;
132
+ amountOut: number;
133
+ amountOutUsd: number;
134
+ txHash: string;
135
+ explorerUrl: string;
136
+ }
103
137
  interface AgentBootstrapResult {
104
138
  key: string;
105
139
  label: string;
@@ -159,6 +193,38 @@ interface RelaiManagementClient {
159
193
  from?: string;
160
194
  cursor?: string;
161
195
  }): Promise<ApiLogsResult>;
196
+ /**
197
+ * Get a bridge quote — fee and net output for a given USD amount.
198
+ * @param amount Amount in USD (e.g. 10.0)
199
+ * @param from Source network: 'solana' | 'skale-base' (default: 'solana')
200
+ */
201
+ getBridgeQuote(amount: number, from?: 'solana' | 'skale-base'): Promise<BridgeQuoteResult>;
202
+ /**
203
+ * Get current USDC liquidity on all bridge networks.
204
+ * Use this before bridging to confirm availability.
205
+ */
206
+ getBridgeBalances(): Promise<BridgeBalances>;
207
+ /**
208
+ * Bridge USDC from Solana to SKALE Base via x402 payment.
209
+ * This call returns HTTP 402 — pass a createX402Client instance to handle payment automatically.
210
+ *
211
+ * @param amount Amount in USD
212
+ * @param destinationWallet EVM address on SKALE Base
213
+ * @param x402Client A configured createX402Client instance for Solana
214
+ */
215
+ bridgeSolanaToSkale(amount: number, destinationWallet: string, x402Client: {
216
+ fetch(url: string, init?: RequestInit): Promise<Response>;
217
+ }): Promise<BridgeResult>;
218
+ /**
219
+ * Bridge USDC from SKALE Base to Solana via x402 payment.
220
+ *
221
+ * @param amount Amount in USD
222
+ * @param destinationWallet Solana public key (base58)
223
+ * @param x402Client A configured createX402Client instance for EVM/SKALE Base
224
+ */
225
+ bridgeSkaleToSolana(amount: number, destinationWallet: string, x402Client: {
226
+ fetch(url: string, init?: RequestInit): Promise<Response>;
227
+ }): Promise<BridgeResult>;
162
228
  }
163
229
  /**
164
230
  * Create a RelAI Management API client.
@@ -180,4 +246,4 @@ interface RelaiManagementClient {
180
246
  */
181
247
  declare function createManagementClient(config: ManagementClientConfig): RelaiManagementClient;
182
248
 
183
- export { type AgentBootstrapResult, type ApiEndpoint, type ApiEndpointInput, type ApiLogItem, type ApiLogsResult, type ApiPayment, type ApiPaymentsResult, type ApiStats, type CreateApiInput, type ManagementClientConfig, type RelaiApi, type RelaiManagementClient, type UpdateApiInput, bootstrapAgentKeyEvm, bootstrapAgentKeySolana, createManagementClient };
249
+ export { type AgentBootstrapResult, type ApiEndpoint, type ApiEndpointInput, type ApiLogItem, type ApiLogsResult, type ApiPayment, type ApiPaymentsResult, type ApiStats, type BridgeBalances, type BridgeQuoteResult, type BridgeResult, type CreateApiInput, type ManagementClientConfig, type RelaiApi, type RelaiManagementClient, type UpdateApiInput, bootstrapAgentKeyEvm, bootstrapAgentKeySolana, createManagementClient };
@@ -100,6 +100,40 @@ interface ApiLogsResult {
100
100
  items: ApiLogItem[];
101
101
  nextCursor: string | null;
102
102
  }
103
+ interface BridgeQuoteResult {
104
+ inputAmount: number;
105
+ outputAmount: number;
106
+ fee: number;
107
+ feeBps: number;
108
+ inputUsd: number;
109
+ outputUsd: number;
110
+ direction: 'solana-to-skale' | 'skale-to-solana';
111
+ from: string;
112
+ to: string;
113
+ }
114
+ interface BridgeBalances {
115
+ solana: {
116
+ atomic: number;
117
+ usd: number;
118
+ };
119
+ skaleBase: {
120
+ atomic: number;
121
+ usd: number;
122
+ };
123
+ base: {
124
+ atomic: number;
125
+ usd: number;
126
+ };
127
+ }
128
+ interface BridgeResult {
129
+ success: boolean;
130
+ direction: 'solana-to-skale' | 'skale-to-solana';
131
+ destinationWallet: string;
132
+ amountOut: number;
133
+ amountOutUsd: number;
134
+ txHash: string;
135
+ explorerUrl: string;
136
+ }
103
137
  interface AgentBootstrapResult {
104
138
  key: string;
105
139
  label: string;
@@ -159,6 +193,38 @@ interface RelaiManagementClient {
159
193
  from?: string;
160
194
  cursor?: string;
161
195
  }): Promise<ApiLogsResult>;
196
+ /**
197
+ * Get a bridge quote — fee and net output for a given USD amount.
198
+ * @param amount Amount in USD (e.g. 10.0)
199
+ * @param from Source network: 'solana' | 'skale-base' (default: 'solana')
200
+ */
201
+ getBridgeQuote(amount: number, from?: 'solana' | 'skale-base'): Promise<BridgeQuoteResult>;
202
+ /**
203
+ * Get current USDC liquidity on all bridge networks.
204
+ * Use this before bridging to confirm availability.
205
+ */
206
+ getBridgeBalances(): Promise<BridgeBalances>;
207
+ /**
208
+ * Bridge USDC from Solana to SKALE Base via x402 payment.
209
+ * This call returns HTTP 402 — pass a createX402Client instance to handle payment automatically.
210
+ *
211
+ * @param amount Amount in USD
212
+ * @param destinationWallet EVM address on SKALE Base
213
+ * @param x402Client A configured createX402Client instance for Solana
214
+ */
215
+ bridgeSolanaToSkale(amount: number, destinationWallet: string, x402Client: {
216
+ fetch(url: string, init?: RequestInit): Promise<Response>;
217
+ }): Promise<BridgeResult>;
218
+ /**
219
+ * Bridge USDC from SKALE Base to Solana via x402 payment.
220
+ *
221
+ * @param amount Amount in USD
222
+ * @param destinationWallet Solana public key (base58)
223
+ * @param x402Client A configured createX402Client instance for EVM/SKALE Base
224
+ */
225
+ bridgeSkaleToSolana(amount: number, destinationWallet: string, x402Client: {
226
+ fetch(url: string, init?: RequestInit): Promise<Response>;
227
+ }): Promise<BridgeResult>;
162
228
  }
163
229
  /**
164
230
  * Create a RelAI Management API client.
@@ -180,4 +246,4 @@ interface RelaiManagementClient {
180
246
  */
181
247
  declare function createManagementClient(config: ManagementClientConfig): RelaiManagementClient;
182
248
 
183
- export { type AgentBootstrapResult, type ApiEndpoint, type ApiEndpointInput, type ApiLogItem, type ApiLogsResult, type ApiPayment, type ApiPaymentsResult, type ApiStats, type CreateApiInput, type ManagementClientConfig, type RelaiApi, type RelaiManagementClient, type UpdateApiInput, bootstrapAgentKeyEvm, bootstrapAgentKeySolana, createManagementClient };
249
+ export { type AgentBootstrapResult, type ApiEndpoint, type ApiEndpointInput, type ApiLogItem, type ApiLogsResult, type ApiPayment, type ApiPaymentsResult, type ApiStats, type BridgeBalances, type BridgeQuoteResult, type BridgeResult, type CreateApiInput, type ManagementClientConfig, type RelaiApi, type RelaiManagementClient, type UpdateApiInput, bootstrapAgentKeyEvm, bootstrapAgentKeySolana, createManagementClient };
@@ -58,6 +58,29 @@ function createManagementClient(config) {
58
58
  }
59
59
  return res.json();
60
60
  }
61
+ async function bridgeReq(method, path, x402Client, body) {
62
+ const res = await x402Client.fetch(`${base}${path}`, {
63
+ method,
64
+ headers: { ...headers, "Content-Type": "application/json" },
65
+ ...body !== void 0 ? { body: JSON.stringify(body) } : {}
66
+ });
67
+ if (!res.ok) {
68
+ const text = await res.text().catch(() => "");
69
+ let parsed = {};
70
+ try {
71
+ parsed = JSON.parse(text);
72
+ } catch {
73
+ }
74
+ if (res.status === 503 && parsed["reason"] === "insufficient_liquidity") {
75
+ const avail = parsed["available"];
76
+ throw new Error(
77
+ `Bridge temporarily unavailable \u2014 insufficient liquidity` + (avail != null ? ` (available: $${Number(avail).toFixed(2)} USDC)` : "")
78
+ );
79
+ }
80
+ throw new Error(`[relai-bridge] ${method} ${path} \u2192 ${res.status}: ${text}`);
81
+ }
82
+ return res.json();
83
+ }
61
84
  return {
62
85
  // ── APIs ──────────────────────────────────────────────────────────────
63
86
  createApi(input) {
@@ -102,6 +125,30 @@ function createManagementClient(config) {
102
125
  if (options.cursor) params.set("cursor", options.cursor);
103
126
  const qs = params.toString() ? `?${params}` : "";
104
127
  return req("GET", `/v1/apis/${apiId}/logs${qs}`);
128
+ },
129
+ // ── Bridge ──────────────────────────────────────────────────
130
+ getBridgeQuote(amount, from = "solana") {
131
+ const params = new URLSearchParams({ amount: String(amount), from });
132
+ return req("GET", `/v1/bridge/quote?${params}`);
133
+ },
134
+ getBridgeBalances() {
135
+ return req("GET", "/v1/bridge/balances");
136
+ },
137
+ async bridgeSolanaToSkale(amount, destinationWallet, x402Client) {
138
+ return bridgeReq(
139
+ "POST",
140
+ "/v1/bridge/solana-to-skale",
141
+ x402Client,
142
+ { amount, destinationWallet }
143
+ );
144
+ },
145
+ async bridgeSkaleToSolana(amount, destinationWallet, x402Client) {
146
+ return bridgeReq(
147
+ "POST",
148
+ "/v1/bridge/skale-to-solana",
149
+ x402Client,
150
+ { amount, destinationWallet }
151
+ );
105
152
  }
106
153
  };
107
154
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/management.ts"],"sourcesContent":["// src/management.ts\n// RelAI Management API client — create and manage monetised APIs programmatically.\n// Docs: https://relai.fi/documentation/management-api\n\nconst RELAI_API_BASE = 'https://api.relai.fi';\nconst BOOTSTRAP_URL = `${RELAI_API_BASE}/mcp/management/bootstrap/agent`;\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ManagementClientConfig {\n /** Service key (sk_live_...) for authenticating management API calls */\n serviceKey: string;\n /** Override base URL (default: https://api.relai.fi) */\n baseUrl?: string;\n}\n\nexport interface RelaiApi {\n apiId: string;\n name: string;\n description?: string;\n baseUrl: string;\n subdomain?: string | null;\n network: string;\n facilitator: string;\n x402Version: number;\n status: string;\n merchantWallet: string;\n solanaWallet?: string | null;\n /** EVM wallet for cross-chain payments. Only relevant when network is Solana. */\n evmCrossChainWallet?: string | null;\n websiteUrl?: string;\n logoUrl?: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface ApiEndpointInput {\n path: string;\n method: string;\n usdPrice: number;\n enabled?: boolean;\n}\n\nexport interface ApiEndpoint extends ApiEndpointInput {\n network: string;\n enabled: boolean;\n}\n\nexport interface CreateApiInput {\n name: string;\n baseUrl: string;\n merchantWallet: string;\n /** Solana wallet for cross-chain payments. Only relevant when network is EVM. */\n solanaWallet?: string;\n /** EVM wallet for cross-chain payments. Only relevant when network is Solana. */\n evmCrossChainWallet?: string;\n network: string;\n description?: string;\n websiteUrl?: string;\n logoUrl?: string;\n endpoints?: ApiEndpointInput[];\n}\n\nexport interface UpdateApiInput {\n name?: string;\n description?: string;\n baseUrl?: string;\n merchantWallet?: string;\n /** Solana wallet for cross-chain payments. Set to null to remove. */\n solanaWallet?: string | null;\n /** EVM wallet for cross-chain payments. Set to null to remove. */\n evmCrossChainWallet?: string | null;\n websiteUrl?: string;\n logoUrl?: string;\n}\n\nexport interface ApiStats {\n apiId: string;\n totalRequests: number;\n totalRevenue: number;\n currency: string;\n}\n\nexport interface ApiPayment {\n transaction: string;\n path: string;\n method: string;\n amount: number;\n currency: string;\n network: string;\n status: string;\n success: boolean;\n payer: string;\n createdAt: string;\n}\n\nexport interface ApiPaymentsResult {\n apiId: string;\n payments: ApiPayment[];\n nextCursor: string | null;\n}\n\nexport interface ApiLogItem {\n id: string;\n timestamp: string;\n method: string;\n path: string;\n status: string;\n cost: number;\n currency: string;\n duration: number;\n transaction: string;\n network: string;\n success: boolean;\n payer: string;\n}\n\nexport interface ApiLogsResult {\n items: ApiLogItem[];\n nextCursor: string | null;\n}\n\nexport interface AgentBootstrapResult {\n key: string;\n label: string;\n active: boolean;\n createdAt: string;\n}\n\n// ============================================================================\n// Agent bootstrap (autonomous key provisioning)\n// ============================================================================\n\n/**\n * Bootstrap a service key for a Solana agent.\n * Run once — store the returned key securely.\n *\n * @param keypair A Solana Keypair (from @solana/web3.js)\n * @param label Human-readable label for the key\n */\nexport async function bootstrapAgentKeySolana(\n keypair: { publicKey: { toBase58(): string }; secretKey: Uint8Array },\n label = 'agent',\n): Promise<AgentBootstrapResult> {\n const { sign } = await import('tweetnacl');\n\n const publicKey = keypair.publicKey.toBase58();\n\n // Step 1 — request challenge\n const challengeRes = await fetch(BOOTSTRAP_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ publicKey }),\n });\n if (!challengeRes.ok) throw new Error(`Challenge request failed: ${challengeRes.status}`);\n const { message } = await challengeRes.json() as { message: string };\n\n // Step 2 — sign\n const msgBytes = new TextEncoder().encode(message);\n const sigBytes = sign.detached(msgBytes, keypair.secretKey);\n const signature = Buffer.from(sigBytes).toString('base64');\n\n // Step 3 — get service key\n const keyRes = await fetch(BOOTSTRAP_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ publicKey, signature, message, label }),\n });\n if (!keyRes.ok) throw new Error(`Key provisioning failed: ${keyRes.status}`);\n return keyRes.json() as Promise<AgentBootstrapResult>;\n}\n\n/**\n * Bootstrap a service key for an EVM agent.\n * Run once — store the returned key securely.\n *\n * @param wallet An ethers.js Wallet or Signer with address + signMessage\n * @param label Human-readable label for the key\n */\nexport async function bootstrapAgentKeyEvm(\n wallet: { address: string; signMessage(message: string): Promise<string> },\n label = 'agent',\n): Promise<AgentBootstrapResult> {\n const publicKey = wallet.address;\n\n // Step 1 — request challenge\n const challengeRes = await fetch(BOOTSTRAP_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ publicKey }),\n });\n if (!challengeRes.ok) throw new Error(`Challenge request failed: ${challengeRes.status}`);\n const { message } = await challengeRes.json() as { message: string };\n\n // Step 2+3 — sign and get key\n const signature = await wallet.signMessage(message);\n const keyRes = await fetch(BOOTSTRAP_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ publicKey, signature, message, label }),\n });\n if (!keyRes.ok) throw new Error(`Key provisioning failed: ${keyRes.status}`);\n return keyRes.json() as Promise<AgentBootstrapResult>;\n}\n\n// ============================================================================\n// Management client\n// ============================================================================\n\nexport interface RelaiManagementClient {\n // APIs\n createApi(input: CreateApiInput): Promise<RelaiApi>;\n listApis(): Promise<RelaiApi[]>;\n getApi(apiId: string): Promise<RelaiApi>;\n updateApi(apiId: string, input: UpdateApiInput): Promise<RelaiApi>;\n deleteApi(apiId: string): Promise<{ success: boolean; apiId: string }>;\n\n // Pricing\n getPricing(apiId: string): Promise<{ apiId: string; endpoints: ApiEndpoint[] }>;\n setPricing(apiId: string, endpoints: ApiEndpointInput[]): Promise<{ success: boolean; apiId: string; updated: number }>;\n\n // Analytics\n getStats(apiId: string): Promise<ApiStats>;\n getPayments(apiId: string, options?: { limit?: number; from?: string; cursor?: string }): Promise<ApiPaymentsResult>;\n getLogs(apiId: string, options?: { limit?: number; from?: string; cursor?: string }): Promise<ApiLogsResult>;\n}\n\n/**\n * Create a RelAI Management API client.\n *\n * @example\n * ```typescript\n * import { createManagementClient } from '@relai-fi/x402/management';\n *\n * const mgmt = createManagementClient({ serviceKey: process.env.RELAI_SERVICE_KEY! });\n *\n * const api = await mgmt.createApi({\n * name: 'My ML API',\n * baseUrl: 'https://inference.example.com',\n * merchantWallet: '0xYourWallet',\n * network: 'base',\n * endpoints: [{ path: '/v1/predict', method: 'post', usdPrice: 0.05 }],\n * });\n * ```\n */\nexport function createManagementClient(config: ManagementClientConfig): RelaiManagementClient {\n const base = (config.baseUrl ?? RELAI_API_BASE).replace(/\\/$/, '');\n const headers = {\n 'X-Service-Key': config.serviceKey,\n 'Content-Type': 'application/json',\n };\n\n async function req<T>(method: string, path: string, body?: unknown): Promise<T> {\n const res = await fetch(`${base}${path}`, {\n method,\n headers,\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n });\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw new Error(`[relai-mgmt] ${method} ${path} → ${res.status}: ${text}`);\n }\n return res.json() as Promise<T>;\n }\n\n return {\n // ── APIs ──────────────────────────────────────────────────────────────\n\n createApi(input) {\n return req<RelaiApi>('POST', '/v1/apis', input);\n },\n\n async listApis() {\n const data = await req<{ apis: RelaiApi[] }>('GET', '/v1/apis');\n return data.apis;\n },\n\n getApi(apiId) {\n return req<RelaiApi>('GET', `/v1/apis/${apiId}`);\n },\n\n updateApi(apiId, input) {\n return req<RelaiApi>('PATCH', `/v1/apis/${apiId}`, input);\n },\n\n deleteApi(apiId) {\n return req<{ success: boolean; apiId: string }>('DELETE', `/v1/apis/${apiId}`);\n },\n\n // ── Pricing ──────────────────────────────────────────────────────────\n\n getPricing(apiId) {\n return req<{ apiId: string; endpoints: ApiEndpoint[] }>('GET', `/v1/apis/${apiId}/pricing`);\n },\n\n setPricing(apiId, endpoints) {\n return req<{ success: boolean; apiId: string; updated: number }>('PUT', `/v1/apis/${apiId}/pricing`, { endpoints });\n },\n\n // ── Analytics ────────────────────────────────────────────────────────\n\n getStats(apiId) {\n return req<ApiStats>('GET', `/v1/apis/${apiId}/stats`);\n },\n\n getPayments(apiId, options = {}) {\n const params = new URLSearchParams();\n if (options.limit) params.set('limit', String(options.limit));\n if (options.from) params.set('from', options.from);\n if (options.cursor) params.set('cursor', options.cursor);\n const qs = params.toString() ? `?${params}` : '';\n return req<ApiPaymentsResult>('GET', `/v1/apis/${apiId}/payments${qs}`);\n },\n\n getLogs(apiId, options = {}) {\n const params = new URLSearchParams();\n if (options.limit) params.set('limit', String(options.limit));\n if (options.from) params.set('from', options.from);\n if (options.cursor) params.set('cursor', options.cursor);\n const qs = params.toString() ? `?${params}` : '';\n return req<ApiLogsResult>('GET', `/v1/apis/${apiId}/logs${qs}`);\n },\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/management.ts"],"sourcesContent":["// src/management.ts\n// RelAI Management API client — create and manage monetised APIs programmatically.\n// Docs: https://relai.fi/documentation/management-api\n\nconst RELAI_API_BASE = 'https://api.relai.fi';\nconst BOOTSTRAP_URL = `${RELAI_API_BASE}/mcp/management/bootstrap/agent`;\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ManagementClientConfig {\n /** Service key (sk_live_...) for authenticating management API calls */\n serviceKey: string;\n /** Override base URL (default: https://api.relai.fi) */\n baseUrl?: string;\n}\n\nexport interface RelaiApi {\n apiId: string;\n name: string;\n description?: string;\n baseUrl: string;\n subdomain?: string | null;\n network: string;\n facilitator: string;\n x402Version: number;\n status: string;\n merchantWallet: string;\n solanaWallet?: string | null;\n /** EVM wallet for cross-chain payments. Only relevant when network is Solana. */\n evmCrossChainWallet?: string | null;\n websiteUrl?: string;\n logoUrl?: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface ApiEndpointInput {\n path: string;\n method: string;\n usdPrice: number;\n enabled?: boolean;\n}\n\nexport interface ApiEndpoint extends ApiEndpointInput {\n network: string;\n enabled: boolean;\n}\n\nexport interface CreateApiInput {\n name: string;\n baseUrl: string;\n merchantWallet: string;\n /** Solana wallet for cross-chain payments. Only relevant when network is EVM. */\n solanaWallet?: string;\n /** EVM wallet for cross-chain payments. Only relevant when network is Solana. */\n evmCrossChainWallet?: string;\n network: string;\n description?: string;\n websiteUrl?: string;\n logoUrl?: string;\n endpoints?: ApiEndpointInput[];\n}\n\nexport interface UpdateApiInput {\n name?: string;\n description?: string;\n baseUrl?: string;\n merchantWallet?: string;\n /** Solana wallet for cross-chain payments. Set to null to remove. */\n solanaWallet?: string | null;\n /** EVM wallet for cross-chain payments. Set to null to remove. */\n evmCrossChainWallet?: string | null;\n websiteUrl?: string;\n logoUrl?: string;\n}\n\nexport interface ApiStats {\n apiId: string;\n totalRequests: number;\n totalRevenue: number;\n currency: string;\n}\n\nexport interface ApiPayment {\n transaction: string;\n path: string;\n method: string;\n amount: number;\n currency: string;\n network: string;\n status: string;\n success: boolean;\n payer: string;\n createdAt: string;\n}\n\nexport interface ApiPaymentsResult {\n apiId: string;\n payments: ApiPayment[];\n nextCursor: string | null;\n}\n\nexport interface ApiLogItem {\n id: string;\n timestamp: string;\n method: string;\n path: string;\n status: string;\n cost: number;\n currency: string;\n duration: number;\n transaction: string;\n network: string;\n success: boolean;\n payer: string;\n}\n\nexport interface ApiLogsResult {\n items: ApiLogItem[];\n nextCursor: string | null;\n}\n\n// ── Bridge types ─────────────────────────────────────────────────────────────\n\nexport interface BridgeQuoteResult {\n inputAmount: number;\n outputAmount: number;\n fee: number;\n feeBps: number;\n inputUsd: number;\n outputUsd: number;\n direction: 'solana-to-skale' | 'skale-to-solana';\n from: string;\n to: string;\n}\n\nexport interface BridgeBalances {\n solana: { atomic: number; usd: number };\n skaleBase: { atomic: number; usd: number };\n base: { atomic: number; usd: number };\n}\n\nexport interface BridgeResult {\n success: boolean;\n direction: 'solana-to-skale' | 'skale-to-solana';\n destinationWallet: string;\n amountOut: number;\n amountOutUsd: number;\n txHash: string;\n explorerUrl: string;\n}\n\nexport interface AgentBootstrapResult {\n key: string;\n label: string;\n active: boolean;\n createdAt: string;\n}\n\n// ============================================================================\n// Agent bootstrap (autonomous key provisioning)\n// ============================================================================\n\n/**\n * Bootstrap a service key for a Solana agent.\n * Run once — store the returned key securely.\n *\n * @param keypair A Solana Keypair (from @solana/web3.js)\n * @param label Human-readable label for the key\n */\nexport async function bootstrapAgentKeySolana(\n keypair: { publicKey: { toBase58(): string }; secretKey: Uint8Array },\n label = 'agent',\n): Promise<AgentBootstrapResult> {\n const { sign } = await import('tweetnacl');\n\n const publicKey = keypair.publicKey.toBase58();\n\n // Step 1 — request challenge\n const challengeRes = await fetch(BOOTSTRAP_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ publicKey }),\n });\n if (!challengeRes.ok) throw new Error(`Challenge request failed: ${challengeRes.status}`);\n const { message } = await challengeRes.json() as { message: string };\n\n // Step 2 — sign\n const msgBytes = new TextEncoder().encode(message);\n const sigBytes = sign.detached(msgBytes, keypair.secretKey);\n const signature = Buffer.from(sigBytes).toString('base64');\n\n // Step 3 — get service key\n const keyRes = await fetch(BOOTSTRAP_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ publicKey, signature, message, label }),\n });\n if (!keyRes.ok) throw new Error(`Key provisioning failed: ${keyRes.status}`);\n return keyRes.json() as Promise<AgentBootstrapResult>;\n}\n\n/**\n * Bootstrap a service key for an EVM agent.\n * Run once — store the returned key securely.\n *\n * @param wallet An ethers.js Wallet or Signer with address + signMessage\n * @param label Human-readable label for the key\n */\nexport async function bootstrapAgentKeyEvm(\n wallet: { address: string; signMessage(message: string): Promise<string> },\n label = 'agent',\n): Promise<AgentBootstrapResult> {\n const publicKey = wallet.address;\n\n // Step 1 — request challenge\n const challengeRes = await fetch(BOOTSTRAP_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ publicKey }),\n });\n if (!challengeRes.ok) throw new Error(`Challenge request failed: ${challengeRes.status}`);\n const { message } = await challengeRes.json() as { message: string };\n\n // Step 2+3 — sign and get key\n const signature = await wallet.signMessage(message);\n const keyRes = await fetch(BOOTSTRAP_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ publicKey, signature, message, label }),\n });\n if (!keyRes.ok) throw new Error(`Key provisioning failed: ${keyRes.status}`);\n return keyRes.json() as Promise<AgentBootstrapResult>;\n}\n\n// ============================================================================\n// Management client\n// ============================================================================\n\nexport interface RelaiManagementClient {\n // APIs\n createApi(input: CreateApiInput): Promise<RelaiApi>;\n listApis(): Promise<RelaiApi[]>;\n getApi(apiId: string): Promise<RelaiApi>;\n updateApi(apiId: string, input: UpdateApiInput): Promise<RelaiApi>;\n deleteApi(apiId: string): Promise<{ success: boolean; apiId: string }>;\n\n // Pricing\n getPricing(apiId: string): Promise<{ apiId: string; endpoints: ApiEndpoint[] }>;\n setPricing(apiId: string, endpoints: ApiEndpointInput[]): Promise<{ success: boolean; apiId: string; updated: number }>;\n\n // Analytics\n getStats(apiId: string): Promise<ApiStats>;\n getPayments(apiId: string, options?: { limit?: number; from?: string; cursor?: string }): Promise<ApiPaymentsResult>;\n getLogs(apiId: string, options?: { limit?: number; from?: string; cursor?: string }): Promise<ApiLogsResult>;\n\n // Bridge\n /**\n * Get a bridge quote — fee and net output for a given USD amount.\n * @param amount Amount in USD (e.g. 10.0)\n * @param from Source network: 'solana' | 'skale-base' (default: 'solana')\n */\n getBridgeQuote(amount: number, from?: 'solana' | 'skale-base'): Promise<BridgeQuoteResult>;\n\n /**\n * Get current USDC liquidity on all bridge networks.\n * Use this before bridging to confirm availability.\n */\n getBridgeBalances(): Promise<BridgeBalances>;\n\n /**\n * Bridge USDC from Solana to SKALE Base via x402 payment.\n * This call returns HTTP 402 — pass a createX402Client instance to handle payment automatically.\n *\n * @param amount Amount in USD\n * @param destinationWallet EVM address on SKALE Base\n * @param x402Client A configured createX402Client instance for Solana\n */\n bridgeSolanaToSkale(\n amount: number,\n destinationWallet: string,\n x402Client: { fetch(url: string, init?: RequestInit): Promise<Response> },\n ): Promise<BridgeResult>;\n\n /**\n * Bridge USDC from SKALE Base to Solana via x402 payment.\n *\n * @param amount Amount in USD\n * @param destinationWallet Solana public key (base58)\n * @param x402Client A configured createX402Client instance for EVM/SKALE Base\n */\n bridgeSkaleToSolana(\n amount: number,\n destinationWallet: string,\n x402Client: { fetch(url: string, init?: RequestInit): Promise<Response> },\n ): Promise<BridgeResult>;\n}\n\n/**\n * Create a RelAI Management API client.\n *\n * @example\n * ```typescript\n * import { createManagementClient } from '@relai-fi/x402/management';\n *\n * const mgmt = createManagementClient({ serviceKey: process.env.RELAI_SERVICE_KEY! });\n *\n * const api = await mgmt.createApi({\n * name: 'My ML API',\n * baseUrl: 'https://inference.example.com',\n * merchantWallet: '0xYourWallet',\n * network: 'base',\n * endpoints: [{ path: '/v1/predict', method: 'post', usdPrice: 0.05 }],\n * });\n * ```\n */\nexport function createManagementClient(config: ManagementClientConfig): RelaiManagementClient {\n const base = (config.baseUrl ?? RELAI_API_BASE).replace(/\\/$/, '');\n const headers = {\n 'X-Service-Key': config.serviceKey,\n 'Content-Type': 'application/json',\n };\n\n async function req<T>(method: string, path: string, body?: unknown): Promise<T> {\n const res = await fetch(`${base}${path}`, {\n method,\n headers,\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n });\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw new Error(`[relai-mgmt] ${method} ${path} → ${res.status}: ${text}`);\n }\n return res.json() as Promise<T>;\n }\n\n async function bridgeReq<T>(\n method: string,\n path: string,\n x402Client: { fetch(url: string, init?: RequestInit): Promise<Response> },\n body?: unknown,\n ): Promise<T> {\n const res = await x402Client.fetch(`${base}${path}`, {\n method,\n headers: { ...headers, 'Content-Type': 'application/json' },\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n });\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n let parsed: Record<string, unknown> = {};\n try { parsed = JSON.parse(text); } catch { /* ignore */ }\n if (res.status === 503 && parsed['reason'] === 'insufficient_liquidity') {\n const avail = parsed['available'] as number | undefined;\n throw new Error(\n `Bridge temporarily unavailable — insufficient liquidity` +\n (avail != null ? ` (available: $${Number(avail).toFixed(2)} USDC)` : ''),\n );\n }\n throw new Error(`[relai-bridge] ${method} ${path} → ${res.status}: ${text}`);\n }\n return res.json() as Promise<T>;\n }\n\n return {\n // ── APIs ──────────────────────────────────────────────────────────────\n\n createApi(input) {\n return req<RelaiApi>('POST', '/v1/apis', input);\n },\n\n async listApis() {\n const data = await req<{ apis: RelaiApi[] }>('GET', '/v1/apis');\n return data.apis;\n },\n\n getApi(apiId) {\n return req<RelaiApi>('GET', `/v1/apis/${apiId}`);\n },\n\n updateApi(apiId, input) {\n return req<RelaiApi>('PATCH', `/v1/apis/${apiId}`, input);\n },\n\n deleteApi(apiId) {\n return req<{ success: boolean; apiId: string }>('DELETE', `/v1/apis/${apiId}`);\n },\n\n // ── Pricing ──────────────────────────────────────────────────────────\n\n getPricing(apiId) {\n return req<{ apiId: string; endpoints: ApiEndpoint[] }>('GET', `/v1/apis/${apiId}/pricing`);\n },\n\n setPricing(apiId, endpoints) {\n return req<{ success: boolean; apiId: string; updated: number }>('PUT', `/v1/apis/${apiId}/pricing`, { endpoints });\n },\n\n // ── Analytics ────────────────────────────────────────────────────────\n\n getStats(apiId) {\n return req<ApiStats>('GET', `/v1/apis/${apiId}/stats`);\n },\n\n getPayments(apiId, options = {}) {\n const params = new URLSearchParams();\n if (options.limit) params.set('limit', String(options.limit));\n if (options.from) params.set('from', options.from);\n if (options.cursor) params.set('cursor', options.cursor);\n const qs = params.toString() ? `?${params}` : '';\n return req<ApiPaymentsResult>('GET', `/v1/apis/${apiId}/payments${qs}`);\n },\n\n getLogs(apiId, options = {}) {\n const params = new URLSearchParams();\n if (options.limit) params.set('limit', String(options.limit));\n if (options.from) params.set('from', options.from);\n if (options.cursor) params.set('cursor', options.cursor);\n const qs = params.toString() ? `?${params}` : '';\n return req<ApiLogsResult>('GET', `/v1/apis/${apiId}/logs${qs}`);\n },\n\n // ── Bridge ──────────────────────────────────────────────────\n\n getBridgeQuote(amount, from = 'solana') {\n const params = new URLSearchParams({ amount: String(amount), from });\n return req<BridgeQuoteResult>('GET', `/v1/bridge/quote?${params}`);\n },\n\n getBridgeBalances() {\n return req<BridgeBalances>('GET', '/v1/bridge/balances');\n },\n\n async bridgeSolanaToSkale(amount, destinationWallet, x402Client) {\n return bridgeReq<BridgeResult>(\n 'POST',\n '/v1/bridge/solana-to-skale',\n x402Client,\n { amount, destinationWallet },\n );\n },\n\n async bridgeSkaleToSolana(amount, destinationWallet, x402Client) {\n return bridgeReq<BridgeResult>(\n 'POST',\n '/v1/bridge/skale-to-solana',\n x402Client,\n { amount, destinationWallet },\n );\n },\n };\n}\n"],"mappings":"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","names":[]}
@@ -35,6 +35,7 @@ var import_spl_token = require("@solana/spl-token");
35
35
  var RELAI_FACILITATOR_URL = "https://facilitator.x402.fi";
36
36
  var NETWORK_CAIP2 = {
37
37
  "solana": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
38
+ "solana-devnet": "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
38
39
  "base": "eip155:8453",
39
40
  "avalanche": "eip155:43114",
40
41
  "skale-base": "eip155:1187947933",
@@ -66,6 +67,14 @@ var NETWORK_TOKENS = {
66
67
  decimals: 6
67
68
  }
68
69
  ],
70
+ "solana-devnet": [
71
+ {
72
+ address: "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU",
73
+ symbol: "USDC",
74
+ name: "USD Coin (Devnet)",
75
+ decimals: 6
76
+ }
77
+ ],
69
78
  "base": [
70
79
  { address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", symbol: "USDC", name: "USD Coin", decimals: 6, domainVersion: "2", isStableUsd: true }
71
80
  ],
@@ -190,6 +199,7 @@ var NETWORK_TOKENS = {
190
199
  };
191
200
  var USDC_ADDRESSES = {
192
201
  "solana": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
202
+ "solana-devnet": "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU",
193
203
  "base": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
194
204
  "avalanche": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
195
205
  "skale-base": "0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20",
@@ -201,6 +211,7 @@ var USDC_ADDRESSES = {
201
211
  };
202
212
  var EXPLORER_TX_URL = {
203
213
  "solana": (tx) => `https://solscan.io/tx/${tx}`,
214
+ "solana-devnet": (tx) => `https://solscan.io/tx/${tx}?cluster=devnet`,
204
215
  "base": (tx) => `https://basescan.org/tx/${tx}`,
205
216
  "avalanche": (tx) => `https://snowtrace.io/tx/${tx}`,
206
217
  "skale-base": (tx) => `https://skale-base-explorer.skalenodes.com/tx/${tx}`,
@@ -212,6 +223,7 @@ var EXPLORER_TX_URL = {
212
223
  };
213
224
  var NETWORK_LABELS = {
214
225
  "solana": "Solana",
226
+ "solana-devnet": "Solana Devnet",
215
227
  "base": "Base",
216
228
  "avalanche": "Avalanche",
217
229
  "skale-base": "SKALE Base",
@@ -227,6 +239,7 @@ var USDC_SOLANA = USDC_ADDRESSES["solana"];
227
239
  var USDC_BASE = USDC_ADDRESSES["base"];
228
240
  var RELAI_NETWORKS = [
229
241
  "solana",
242
+ "solana-devnet",
230
243
  "base",
231
244
  "avalanche",
232
245
  "skale-base",
@@ -237,7 +250,7 @@ var RELAI_NETWORKS = [
237
250
  "telos"
238
251
  ];
239
252
  function isSolana(network) {
240
- return network === "solana" || network.startsWith("solana:");
253
+ return network === "solana" || network === "solana-devnet" || network.startsWith("solana:");
241
254
  }
242
255
  function isEvm(network) {
243
256
  return ["base", "avalanche", "skale-base", "skale-base-sepolia", "skale-bite", "polygon", "ethereum", "telos"].includes(network) || network.startsWith("eip155:");