Skip to content
Merged
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
4 changes: 2 additions & 2 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ Create a new payment session for a customer.
"amount": 1000,
"expired": "2025-10-13T12:00:00Z",
"completed": false,
"session_url": "https://zpaynow.com/pay/abc123",
"session_url": "https://zpaynow.com/sessions/abc123",
"merchant": "Your Store Name",
"chains": [
{
Expand Down Expand Up @@ -414,5 +414,5 @@ For higher limits, contact support or consider self-hosting.
## Support

For questions and issues:
- GitHub: [https://github.com/ZeroPayDev/zeropay/issues](https://github.com/ZeroPayDev/zeropay/issues)
- GitHub: [https://github.com/zpaynow/zeropay/issues](https://github.com/zpaynow/zeropay/issues)
- Platform Support: [https://zpaynow.com/support](https://zpaynow.com/support)

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

6 changes: 2 additions & 4 deletions api/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,8 @@ async fn main() {
.await
.unwrap();
for asset in c.assets {
scheme
.asset(&asset.address, &asset.name, &asset.version)
.await
.unwrap();
// try x402 asset
scheme.asset(&asset.address).await.unwrap();
}
facilitator.register(scheme);
}
Expand Down
2 changes: 1 addition & 1 deletion api/src/models/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ impl Session {
pub async fn list_unused(customer: i32, db: &PgPool) -> Result<Vec<Session>> {
let res = query_as!(
Self,
"SELECT * FROM sessions WHERE customer=$1 AND deposit IS NULL",
"SELECT * FROM sessions WHERE customer=$1 AND deposit IS NULL ORDER BY id DESC",
customer,
)
.fetch_all(db)
Expand Down
2 changes: 1 addition & 1 deletion docs/AI_INTEGRATION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ ZeroPay is a cryptocurrency payment gateway that:

```javascript
const ZEROPAY_CONFIG = {
apiUrl: "https://api.zeropay.example.com", // Replace with actual API URL
apiUrl: "https://api.zpaynow.com", // Replace with actual API URL
apiKey: "your-api-key-here", // Provided by ZeroPay
webhookSecret: "your-api-key-here", // Same as apiKey for HMAC verification
};
Expand Down
18 changes: 3 additions & 15 deletions docs/API_DOCUMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ ZeroPay is a payment gateway that allows you to accept cryptocurrency payments (
### Base URL

```
https://api.zeropay.example.com
https://api.zpaynow.com
```

Replace with your actual ZeroPay API URL provided during onboarding.
Expand Down Expand Up @@ -78,7 +78,7 @@ Create a new payment session for a customer.
**Example Request:**

```bash
curl -X POST "https://api.zeropay.example.com/sessions?apikey=your_api_key" \
curl -X POST "https://api.zpaynow.com/sessions?apikey=your_api_key" \
-H "Content-Type: application/json" \
-d '{
"customer": "user_12345",
Expand Down Expand Up @@ -147,7 +147,7 @@ Retrieve details of an existing payment session.
**Example Request:**

```bash
curl "https://api.zeropay.example.com/sessions/42?apikey=your_api_key"
curl "https://api.zpaynow.com/sessions/42?apikey=your_api_key"
```

**Success Response (200 OK):**
Expand Down Expand Up @@ -826,18 +826,6 @@ A: Verify:

---

## Support

Need help? Contact us:

- Email: support@zeropay.example.com
- Documentation: https://docs.zeropay.example.com
- Status Page: https://status.zeropay.example.com

Include your API key (first 8 characters only) and session IDs when reporting issues.

---

## Changelog

### v1.0.0 (Current)
Expand Down
2 changes: 1 addition & 1 deletion scanner/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ impl<S: ScannerStorage> ScannerService<S> {
let mut values = t.split(":");
let name: String = values.next().unwrap_or_default().to_owned();
let token: Address = values.next().unwrap_or_default().parse()?;
let version = values.next().unwrap_or_default().to_owned();
let version = values.next().unwrap_or_default().to_owned(); // EIP-3009 x402
let decimal = evm::get_token_decimal(token, provider.clone()).await?;
let identity = format!("{}:{}", config.chain_name, name);

Expand Down
11 changes: 5 additions & 6 deletions x402.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ Submit payment authorization and settle:
curl -X POST "http://localhost:9000/x402/payments?apikey=your-api-key" \
-H "Content-Type: application/json" \
-d '{
"payment_payload": {
"x402_version": 1,
"paymentPayload": {
"x402Version": 1,
"scheme": "exact",
"network": "base-sepolia",
"payload": {
Expand All @@ -77,7 +77,7 @@ curl -X POST "http://localhost:9000/x402/payments?apikey=your-api-key" \
}
}
},
"payment_requirements": {...}
"paymentRequirements": {...}
}'
```

Expand Down Expand Up @@ -121,12 +121,11 @@ let response = facilitator.pay(&url, payload).await?;
## Additional Resources

- **[AI Integration Guide](./docs/AI_INTEGRATION_GUIDE.md)** - Prompt and guide for AI agents to integrate with ZeroPay API
- **[x402 Specification](https://github.com/zeropaydev/x402)** - Official x402 protocol specification
- **[x402 Specification](https://github.com/coinbase/x402)** - Official x402 protocol specification
- **[API Documentation](./docs/API_DOCUMENTATION.md)** - Detailed API reference

## Support

For x402-specific questions and issues:
- **x402 Protocol Spec**: [https://github.com/zeropaydev/x402](https://github.com/zeropaydev/x402)
- **GitHub Issues**: [https://github.com/ZeroPayDev/zeropay/issues](https://github.com/ZeroPayDev/zeropay/issues)
- **x402 Protocol Spec**: [https://github.com/coinbase/x402](https://github.com/coinbase/x402)
- **Platform Support**: hi@zpaynow.com
13 changes: 13 additions & 0 deletions x402/EIP3009.json
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,19 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "version",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "symbol",
Expand Down
48 changes: 32 additions & 16 deletions x402/src/scheme/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ sol! {
address from;
address to;
uint256 value;
uint256 valid_after;
uint256 valid_before;
uint256 validAfter;
uint256 validBefore;
bytes32 nonce;
}
}
Expand All @@ -54,8 +54,8 @@ impl TransferWithAuthorization {
from,
to,
value,
valid_after,
valid_before,
validAfter: valid_after,
validBefore: valid_before,
nonce,
})
}
Expand Down Expand Up @@ -132,13 +132,15 @@ impl EvmScheme {
///
/// # Arguments
/// * `addr` - The token contract address
/// * `name` - The token name for EIP-712 domain (e.g., "USD Coin")
/// * `version` - The token version for EIP-712 domain (e.g., "2")
///
/// # Returns
/// * `Ok(())` if the token is valid and supports EIP-3009
/// * `Err` if the token is invalid or doesn't support EIP-3009
pub async fn asset(&mut self, addr: &str, name: &str, version: &str) -> Result<()> {
///
/// # Note
/// This function automatically reads the token name and version from the contract
/// to ensure they match the contract's DOMAIN_SEPARATOR for EIP-712 signing
pub async fn asset(&mut self, addr: &str) -> Result<()> {
let token_address: Address = addr.parse()?;

// Create provider and contract instance
Expand All @@ -155,18 +157,32 @@ impl EvmScheme {
.call()
.await?;

// Create EIP-712 domain
let domain = create_eip712_domain(
name.to_string(),
version.to_string(),
self.chain_id,
token_address,
);
// Read the contract's actual name, version, and DOMAIN_SEPARATOR
let name = contract.name().call().await?;
let version = contract.version().call().await?;
let contract_domain_separator = contract.DOMAIN_SEPARATOR().call().await?;

// Create EIP-712 domain with contract's actual name/version
let domain =
create_eip712_domain(name.clone(), version.clone(), self.chain_id, token_address);
let computed_domain_separator = domain.hash_struct();

// Verify the computed domain matches the contract's DOMAIN_SEPARATOR
if computed_domain_separator != contract_domain_separator {
return Err(anyhow::anyhow!(
"Domain separator mismatch! Contract DOMAIN_SEPARATOR doesn't match computed value. \
Contract name: '{}', version: '{}', chain ID: {}",
name,
version,
self.chain_id
));
}

// Create and store the asset
// Create and store the asset with contract's actual parameters
let extra = json!({
"name": name,
"version": version
"version": version,
"chainId": self.chain_id,
});
let asset = EvmAsset {
name: name.to_owned(),
Expand Down