Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions a2a/a2a-service/host/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@
from a2a.server.events.event_queue import EventQueue
from a2a.utils import new_task

from .pipeline import PaywallPipeline
from .service import PaywallService
from .lib.openai.client import OpenAIClient
from .lib.openai.planner import PaywallPlanner
from host.pipeline import PaywallPipeline
from host.service import PaywallService
from host.lib.openai.client import OpenAIClient
from host.lib.openai.planner import PaywallPlanner


class PaywallExecutor(AgentExecutor):
Expand Down
2 changes: 1 addition & 1 deletion a2a/a2a-service/host/lib/enums/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
while retaining enum semantics.
"""

from .common import AutoStrEnum
from host.lib.enums.common import AutoStrEnum


class StatusMessage(AutoStrEnum):
Expand Down
2 changes: 1 addition & 1 deletion a2a/a2a-service/host/lib/enums/name.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
agents, pipelines, and clients.
"""

from .common import AutoStrEnum
from host.lib.enums.common import AutoStrEnum


class ArtifactName(AutoStrEnum):
Expand Down
2 changes: 1 addition & 1 deletion a2a/a2a-service/host/lib/errors/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import logging
from typing import Any, Callable

from .app_error import AppError
from host.lib.errors.app_error import AppError

logger = logging.getLogger(__name__)

Expand Down
4 changes: 2 additions & 2 deletions a2a/a2a-service/host/lib/openai/planner.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
import json
from typing import Any, Dict, List, Optional

from ..errors.app_error import LlmError
from ..errors.decorators import handle_errors
from host.lib.errors.app_error import LlmError
from host.lib.errors.decorators import handle_errors


class PaywallPlanner:
Expand Down
4 changes: 2 additions & 2 deletions a2a/a2a-service/host/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
from a2a.server.tasks import InMemoryPushNotificationConfigStore, InMemoryTaskStore
from a2a.types import AgentCapabilities, AgentCard, AgentSkill

from .executor import PaywallExecutor
from .lib.config import settings
from host.executor import PaywallExecutor
from host.lib.config import settings


async def main() -> None:
Expand Down
8 changes: 4 additions & 4 deletions a2a/a2a-service/host/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@

from typing import Any, Dict, List, Optional

from .lib.a2a.events import progress, finish, fail
from .lib.enums.message import FailMessage, ProgressMessage
from .lib.enums.name import ArtifactName
from .lib.errors.app_error import AppError
from host.lib.a2a.events import progress, finish, fail
from host.lib.enums.message import FailMessage, ProgressMessage
from host.lib.enums.name import ArtifactName
from host.lib.errors.app_error import AppError


class PaywallPipeline:
Expand Down
13 changes: 8 additions & 5 deletions a2a/a2a-service/host/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,14 @@
import httpx
from eth_account import Account

from .lib.a2a.discovery import fetch_agent_card
from .lib.errors.app_error import ConfigError, NetworkError, ValidationError
from .lib.errors.decorators import handle_errors

from crypto_com_facilitator_client import Facilitator, CronosNetwork
from crypto_com_facilitator_client.integrations.facilitator_interface import (
CronosNetwork,
)
from crypto_com_facilitator_client.lib.client.index import Facilitator

from host.lib.a2a.discovery import fetch_agent_card
from host.lib.errors.app_error import ConfigError, NetworkError, ValidationError
from host.lib.errors.decorators import handle_errors


X402_PROTOCOL = "x402"
Expand Down
2 changes: 2 additions & 0 deletions a2a/a2a-service/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ dependencies = [

"rich>=13.7.0",
"typing-extensions>=4.12.2",

"crypto-com-facilitator-client>=1.0.4",
]

[project.optional-dependencies]
Expand Down
2 changes: 1 addition & 1 deletion a2a/a2a-service/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ sqlalchemy[asyncio]>=2.0.29
asyncpg>=0.29.0
greenlet>=3.0.3
openai>=2.0.0
crypto_com_facilitator_client>=1.0.3
crypto-com-facilitator-client>=1.0.4
8 changes: 4 additions & 4 deletions a2a/resource-service/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion a2a/resource-service/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"test": "jest"
},
"dependencies": {
"@crypto.com/facilitator-client": "^1.0.1",
"@crypto.com/facilitator-client": "^1.0.3",
"cors": "2.8.5",
"dotenv": "^16.4.5",
"ethers": "^6.15.0",
Expand Down
8 changes: 4 additions & 4 deletions paywall/resource-app/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion paywall/resource-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"test:coverage": "vitest run --coverage"
},
"dependencies": {
"@crypto.com/facilitator-client": "^1.0.1",
"@crypto.com/facilitator-client": "^1.0.3",
"@types/react-google-recaptcha": "^2.1.9",
"react": "^18.3.1",
"react-dom": "^18.3.1",
Expand Down
3 changes: 2 additions & 1 deletion paywall/resource-app/src/hooks/useX402Flow.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useCallback, useMemo, useState } from 'react';
import { Facilitator } from '@crypto.com/facilitator-client';
import { createApiClient } from '../integration/api';
import type { PaymentChallenge } from '../integration/api.interfaces';
import { ensureWallet } from '../utils/wallet';
import { ensureCronosChain } from '../utils/cronos';
import { Facilitator } from '@crypto.com/facilitator-client';

/**
* Options for configuring the X402 payment flow hook.
Expand Down Expand Up @@ -109,6 +109,7 @@ export function useX402Flow(options: UseX402FlowOptions): UseX402FlowResult {
setStatus('Signing EIP-3009 payment header in wallet...');

const fac = new Facilitator({ network: accepts0.network });

const paymentHeader = await fac.generatePaymentHeader({
to: accepts0.payTo,
value: accepts0.maxAmountRequired,
Expand Down
68 changes: 39 additions & 29 deletions paywall/resource-app/src/utils/cronos.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
import type { CronosNetwork } from '@crypto.com/facilitator-client';

const CRONOS = {
mainnet: {
chainId: '0x19',
chainName: 'Cronos Mainnet',
nativeCurrency: { name: 'CRO', symbol: 'CRO', decimals: 18 },
rpcUrls: ['https://evm.cronos.org'],
blockExplorerUrls: ['https://cronoscan.com'],
},
testnet: {
chainId: '0x152',
chainName: 'Cronos Testnet',
nativeCurrency: { name: 'tCRO', symbol: 'tCRO', decimals: 18 },
rpcUrls: ['https://evm-t3.cronos.org'],
blockExplorerUrls: ['https://cronos.org/explorer/testnet3'],
},
} as const;

/**
* Ensures the user's wallet is connected to the required Cronos network.
*
Expand All @@ -21,42 +38,35 @@ import type { CronosNetwork } from '@crypto.com/facilitator-client';
* @throws If the wallet rejects the request or the provider is unavailable.
*/
export async function ensureCronosChain(target: CronosNetwork): Promise<void> {
/**
* Cronos chain id in hex format as expected by EIP-3085 / EIP-3326.
*
* @remarks
* - `0x19` → Cronos Mainnet (25)
* - `0x152` → Cronos Testnet (338)
*/
const chainIdHex = target === 'cronos-mainnet' ? '0x19' : '0x152';

const anyWindow = window as any;
const eth = anyWindow?.ethereum;
if (!eth?.request) throw new Error('No EIP-1193 provider found (window.ethereum missing)');

try {
await anyWindow.ethereum.request({
const cfg = target === 'cronos-mainnet' ? CRONOS.mainnet : CRONOS.testnet;

const switchTo = async () =>
eth.request({
method: 'wallet_switchEthereumChain',
params: [{ chainId: chainIdHex }],
params: [{ chainId: cfg.chainId }],
});

try {
await switchTo();
return;
} catch (e: any) {
/**
* Error code `4902` indicates the requested chain is not yet added
* to the user's wallet.
*/
if (e?.code === 4902 && target === 'cronos-testnet') {
await anyWindow.ethereum.request({
// 4902 = chain not added
if (e?.code === 4902) {
await eth.request({
method: 'wallet_addEthereumChain',
params: [
{
chainId: '0x152',
chainName: 'Cronos Testnet',
nativeCurrency: { name: 'tCRO', symbol: 'tCRO', decimals: 18 },
rpcUrls: ['https://evm-t3.cronos.org'],
blockExplorerUrls: ['https://cronos.org/explorer/testnet3'],
},
],
params: [cfg],
});
} else {
throw e;

// IMPORTANT: switch after adding
await switchTo();
return;
}

// user rejected, or other error
throw e;
}
}
8 changes: 4 additions & 4 deletions paywall/resource-service/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion paywall/resource-service/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"test": "jest"
},
"dependencies": {
"@crypto.com/facilitator-client": "^1.0.1",
"@crypto.com/facilitator-client": "^1.0.3",
"cors": "2.8.5",
"dotenv": "^16.4.5",
"ethers": "^6.15.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
import crypto from 'node:crypto';
import type { Request, Response, NextFunction } from 'express';
import type {
Facilitator,
VerifyRequest,
X402VerifyResponse,
X402SettleResponse,
} from '@crypto.com/facilitator-client';
import type {
Accepts,
PaidRecord,
Expand All @@ -14,6 +8,7 @@ import type {
X402Response,
} from '../../services/resource.interface.js';
import { PaymentStatus } from '../interfaces/api.interface.js';
import { Facilitator, VerifyRequest, X402SettleResponse, X402VerifyResponse } from '@crypto.com/facilitator-client';

/**
* In-memory entitlement store keyed by an entitlement key (typically a payment id).
Expand Down
2 changes: 1 addition & 1 deletion paywall/resource-service/src/services/resource.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Facilitator, CronosNetwork, PaymentRequirements } from '@crypto.com/facilitator-client';
import { CronosNetwork, Facilitator, PaymentRequirements } from '@crypto.com/facilitator-client';
import { handleX402Payment } from '../lib/middlewares/require.middleware.js';

const NETWORK = (process.env.NETWORK ?? 'cronos-testnet') as CronosNetwork;
Expand Down