uvd-x402-sdk 2.5.0 → 2.10.0
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.
- package/README.md +380 -3
- package/dist/adapters/index.d.mts +1 -1
- package/dist/adapters/index.d.ts +1 -1
- package/dist/adapters/index.js +82 -1
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/index.mjs +82 -1
- package/dist/adapters/index.mjs.map +1 -1
- package/dist/backend/index.d.mts +1036 -0
- package/dist/backend/index.d.ts +1036 -0
- package/dist/backend/index.js +1722 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/index.mjs +1704 -0
- package/dist/backend/index.mjs.map +1 -0
- package/dist/{index-BrFeSWKm.d.mts → index-C60c_e5z.d.mts} +13 -4
- package/dist/{index-DR2vXt-c.d.mts → index-D-dO_FoP.d.mts} +70 -4
- package/dist/{index-DR2vXt-c.d.ts → index-D-dO_FoP.d.ts} +70 -4
- package/dist/{index-BYX9BU79.d.ts → index-VIOUicmO.d.ts} +13 -4
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +115 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +110 -2
- package/dist/index.mjs.map +1 -1
- package/dist/providers/algorand/index.d.mts +86 -0
- package/dist/providers/algorand/index.d.ts +86 -0
- package/dist/providers/algorand/index.js +903 -0
- package/dist/providers/algorand/index.js.map +1 -0
- package/dist/providers/algorand/index.mjs +898 -0
- package/dist/providers/algorand/index.mjs.map +1 -0
- package/dist/providers/evm/index.d.mts +1 -1
- package/dist/providers/evm/index.d.ts +1 -1
- package/dist/providers/evm/index.js +78 -1
- package/dist/providers/evm/index.js.map +1 -1
- package/dist/providers/evm/index.mjs +78 -1
- package/dist/providers/evm/index.mjs.map +1 -1
- package/dist/providers/near/index.d.mts +1 -1
- package/dist/providers/near/index.d.ts +1 -1
- package/dist/providers/near/index.js +78 -1
- package/dist/providers/near/index.js.map +1 -1
- package/dist/providers/near/index.mjs +78 -1
- package/dist/providers/near/index.mjs.map +1 -1
- package/dist/providers/solana/index.d.mts +1 -1
- package/dist/providers/solana/index.d.ts +1 -1
- package/dist/providers/solana/index.js +78 -1
- package/dist/providers/solana/index.js.map +1 -1
- package/dist/providers/solana/index.mjs +78 -1
- package/dist/providers/solana/index.mjs.map +1 -1
- package/dist/providers/stellar/index.d.mts +1 -1
- package/dist/providers/stellar/index.d.ts +1 -1
- package/dist/providers/stellar/index.js +78 -1
- package/dist/providers/stellar/index.js.map +1 -1
- package/dist/providers/stellar/index.mjs +78 -1
- package/dist/providers/stellar/index.mjs.map +1 -1
- package/dist/react/index.d.mts +3 -3
- package/dist/react/index.d.ts +3 -3
- package/dist/react/index.js +82 -1
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +82 -1
- package/dist/react/index.mjs.map +1 -1
- package/dist/utils/index.d.mts +57 -5
- package/dist/utils/index.d.ts +57 -5
- package/dist/utils/index.js +96 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/index.mjs +93 -2
- package/dist/utils/index.mjs.map +1 -1
- package/package.json +24 -3
- package/src/adapters/wagmi.ts +4 -0
- package/src/backend/index.ts +2131 -0
- package/src/chains/index.ts +94 -2
- package/src/client/X402Client.ts +4 -0
- package/src/index.ts +26 -1
- package/src/providers/algorand/index.ts +356 -0
- package/src/types/index.ts +78 -3
- package/src/utils/index.ts +4 -0
- package/src/utils/validation.ts +76 -3
package/README.md
CHANGED
|
@@ -2,15 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
> Gasless crypto payments across 14 blockchain networks using the x402 protocol.
|
|
4
4
|
|
|
5
|
-
The x402 SDK enables any application to accept stablecoin payments (USDC, EURC, AUSD, PYUSD) without requiring users to pay gas fees. Users sign a message or transaction, and the Ultravioleta facilitator handles on-chain settlement.
|
|
5
|
+
The x402 SDK enables any application to accept stablecoin payments (USDC, EURC, AUSD, PYUSD, USDT) without requiring users to pay gas fees. Users sign a message or transaction, and the Ultravioleta facilitator handles on-chain settlement.
|
|
6
6
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
9
|
- **14 Supported Networks**: EVM chains, Solana, Fogo, Stellar, and NEAR
|
|
10
|
-
- **Multi-Stablecoin**: USDC, EURC, AUSD, PYUSD support on EVM chains
|
|
10
|
+
- **Multi-Stablecoin**: USDC, EURC, AUSD, PYUSD, USDT support on EVM chains
|
|
11
11
|
- **x402 v1 & v2**: Full support for both protocol versions with automatic detection
|
|
12
12
|
- **Gasless Payments**: Users never pay gas - the facilitator covers all network fees
|
|
13
13
|
- **Multi-Network**: Accept payments on multiple networks simultaneously
|
|
14
|
+
- **Backend Utilities**: Server-side helpers for payment verification and settlement
|
|
15
|
+
- **Bazaar Discovery**: Discover and register x402-enabled resources
|
|
16
|
+
- **Escrow & Refunds**: Hold payments in escrow with refund and dispute support
|
|
14
17
|
- **Type-Safe**: Comprehensive TypeScript definitions
|
|
15
18
|
- **Framework Agnostic**: Works with any JavaScript framework
|
|
16
19
|
- **React Hooks**: First-class React integration
|
|
@@ -680,8 +683,9 @@ EVM chains support multiple stablecoins beyond USDC. Token availability varies b
|
|
|
680
683
|
|-------|-------------|----------|--------|
|
|
681
684
|
| USDC | USD Coin (Circle) | 6 | All EVM chains |
|
|
682
685
|
| EURC | Euro Coin (Circle) | 6 | Ethereum, Base, Avalanche |
|
|
683
|
-
| AUSD | Agora
|
|
686
|
+
| AUSD | Agora Dollar | 6 | Ethereum, Avalanche, Polygon, Arbitrum, Monad |
|
|
684
687
|
| PYUSD | PayPal USD | 6 | Ethereum |
|
|
688
|
+
| USDT | Tether USD (USDT0 Omnichain via LayerZero) | 6 | Ethereum, Arbitrum |
|
|
685
689
|
|
|
686
690
|
### Basic Usage
|
|
687
691
|
|
|
@@ -1076,6 +1080,379 @@ try {
|
|
|
1076
1080
|
|
|
1077
1081
|
---
|
|
1078
1082
|
|
|
1083
|
+
## Backend Utilities
|
|
1084
|
+
|
|
1085
|
+
The SDK includes comprehensive server-side utilities for handling x402 payments.
|
|
1086
|
+
|
|
1087
|
+
### Payment Flow Diagram
|
|
1088
|
+
|
|
1089
|
+
```
|
|
1090
|
+
┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ ┌──────────────┐
|
|
1091
|
+
│ Client │ │ Your API │ │ Facilitator │ │ Blockchain │
|
|
1092
|
+
└──────┬──────┘ └──────┬──────┘ └────────┬────────┘ └──────┬───────┘
|
|
1093
|
+
│ │ │ │
|
|
1094
|
+
│ 1. Request resource (no payment) │ │
|
|
1095
|
+
│ ────────────────> │ │ │
|
|
1096
|
+
│ │ │ │
|
|
1097
|
+
│ 2. 402 Payment Required │ │
|
|
1098
|
+
│ <──────────────── │ │ │
|
|
1099
|
+
│ │ │ │
|
|
1100
|
+
│ 3. User signs payment │ │
|
|
1101
|
+
│ (wallet popup) │ │ │
|
|
1102
|
+
│ │ │ │
|
|
1103
|
+
│ 4. Request with X-PAYMENT header │ │
|
|
1104
|
+
│ ────────────────> │ │ │
|
|
1105
|
+
│ │ │ │
|
|
1106
|
+
│ │ 5. Verify payment │ │
|
|
1107
|
+
│ │ ────────────────────> │
|
|
1108
|
+
│ │ │ │
|
|
1109
|
+
│ │ 6. Payment valid │ │
|
|
1110
|
+
│ │ <────────────────── │ │
|
|
1111
|
+
│ │ │ │
|
|
1112
|
+
│ 7. Provide resource │ │
|
|
1113
|
+
│ <──────────────── │ │ │
|
|
1114
|
+
│ │ │ │
|
|
1115
|
+
│ │ 8. Settle payment │ │
|
|
1116
|
+
│ │ ────────────────────> │
|
|
1117
|
+
│ │ │ │
|
|
1118
|
+
│ │ │ 9. Submit tx │
|
|
1119
|
+
│ │ │ ───────────────────>│
|
|
1120
|
+
│ │ │ │
|
|
1121
|
+
│ │ │ 10. Confirmed │
|
|
1122
|
+
│ │ │ <───────────────────│
|
|
1123
|
+
│ │ │ │
|
|
1124
|
+
│ │ 11. Settlement done │ │
|
|
1125
|
+
│ │ <────────────────── │ │
|
|
1126
|
+
└ └ └ └
|
|
1127
|
+
```
|
|
1128
|
+
|
|
1129
|
+
### Basic Backend Setup
|
|
1130
|
+
|
|
1131
|
+
```typescript
|
|
1132
|
+
import {
|
|
1133
|
+
parsePaymentHeader,
|
|
1134
|
+
extractPaymentFromHeaders,
|
|
1135
|
+
buildPaymentRequirements,
|
|
1136
|
+
FacilitatorClient,
|
|
1137
|
+
create402Response,
|
|
1138
|
+
X402_CORS_HEADERS,
|
|
1139
|
+
} from 'uvd-x402-sdk/backend';
|
|
1140
|
+
|
|
1141
|
+
// Configure CORS
|
|
1142
|
+
app.use((req, res, next) => {
|
|
1143
|
+
Object.entries(X402_CORS_HEADERS).forEach(([key, value]) => {
|
|
1144
|
+
res.setHeader(key, value);
|
|
1145
|
+
});
|
|
1146
|
+
next();
|
|
1147
|
+
});
|
|
1148
|
+
|
|
1149
|
+
// Protected endpoint
|
|
1150
|
+
app.post('/api/premium', async (req, res) => {
|
|
1151
|
+
// Extract payment from headers
|
|
1152
|
+
const payment = extractPaymentFromHeaders(req.headers);
|
|
1153
|
+
|
|
1154
|
+
if (!payment) {
|
|
1155
|
+
// Return 402 Payment Required
|
|
1156
|
+
const { status, headers, body } = create402Response({
|
|
1157
|
+
amount: '1.00',
|
|
1158
|
+
recipient: process.env.PAYMENT_RECIPIENT,
|
|
1159
|
+
resource: 'https://api.example.com/premium',
|
|
1160
|
+
chainName: 'base',
|
|
1161
|
+
});
|
|
1162
|
+
return res.status(status).set(headers).json(body);
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
// Verify payment with facilitator
|
|
1166
|
+
const client = new FacilitatorClient();
|
|
1167
|
+
const requirements = buildPaymentRequirements({
|
|
1168
|
+
amount: '1.00',
|
|
1169
|
+
recipient: process.env.PAYMENT_RECIPIENT,
|
|
1170
|
+
resource: 'https://api.example.com/premium',
|
|
1171
|
+
});
|
|
1172
|
+
|
|
1173
|
+
const verifyResult = await client.verify(payment, requirements);
|
|
1174
|
+
|
|
1175
|
+
if (!verifyResult.isValid) {
|
|
1176
|
+
return res.status(402).json({
|
|
1177
|
+
error: 'Payment verification failed',
|
|
1178
|
+
reason: verifyResult.invalidReason,
|
|
1179
|
+
});
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
// Provide the resource
|
|
1183
|
+
res.json({ data: 'premium content' });
|
|
1184
|
+
|
|
1185
|
+
// Settle payment after response
|
|
1186
|
+
await client.settle(payment, requirements);
|
|
1187
|
+
});
|
|
1188
|
+
```
|
|
1189
|
+
|
|
1190
|
+
### Using Payment Middleware
|
|
1191
|
+
|
|
1192
|
+
```typescript
|
|
1193
|
+
import { createPaymentMiddleware } from 'uvd-x402-sdk/backend';
|
|
1194
|
+
|
|
1195
|
+
const paymentMiddleware = createPaymentMiddleware(
|
|
1196
|
+
(req) => ({
|
|
1197
|
+
amount: '1.00',
|
|
1198
|
+
recipient: process.env.PAYMENT_RECIPIENT,
|
|
1199
|
+
resource: `${req.protocol}://${req.get('host')}${req.originalUrl}`,
|
|
1200
|
+
})
|
|
1201
|
+
);
|
|
1202
|
+
|
|
1203
|
+
// Apply to specific routes
|
|
1204
|
+
app.get('/premium/*', paymentMiddleware, (req, res) => {
|
|
1205
|
+
res.json({ premium: 'data' });
|
|
1206
|
+
});
|
|
1207
|
+
```
|
|
1208
|
+
|
|
1209
|
+
### FacilitatorClient API
|
|
1210
|
+
|
|
1211
|
+
```typescript
|
|
1212
|
+
const client = new FacilitatorClient({
|
|
1213
|
+
baseUrl: 'https://facilitator.ultravioletadao.xyz', // default
|
|
1214
|
+
timeout: 30000, // default: 30 seconds
|
|
1215
|
+
});
|
|
1216
|
+
|
|
1217
|
+
// Verify a payment
|
|
1218
|
+
const verifyResult = await client.verify(payment, requirements);
|
|
1219
|
+
// Returns: { isValid: boolean, invalidReason?: string, payer?: string }
|
|
1220
|
+
|
|
1221
|
+
// Settle a payment (execute on-chain)
|
|
1222
|
+
const settleResult = await client.settle(payment, requirements);
|
|
1223
|
+
// Returns: { success: boolean, transactionHash?: string, error?: string }
|
|
1224
|
+
|
|
1225
|
+
// Combined verify + settle
|
|
1226
|
+
const result = await client.verifyAndSettle(payment, requirements);
|
|
1227
|
+
// Returns: { verified: boolean, settled: boolean, transactionHash?: string, error?: string }
|
|
1228
|
+
|
|
1229
|
+
// Health check
|
|
1230
|
+
const isHealthy = await client.healthCheck();
|
|
1231
|
+
```
|
|
1232
|
+
|
|
1233
|
+
---
|
|
1234
|
+
|
|
1235
|
+
## Bazaar Discovery API
|
|
1236
|
+
|
|
1237
|
+
Discover and register x402-enabled resources across the ecosystem.
|
|
1238
|
+
|
|
1239
|
+
```typescript
|
|
1240
|
+
import { BazaarClient } from 'uvd-x402-sdk/backend';
|
|
1241
|
+
|
|
1242
|
+
// Discover resources (no auth required)
|
|
1243
|
+
const bazaar = new BazaarClient();
|
|
1244
|
+
|
|
1245
|
+
const results = await bazaar.discover({
|
|
1246
|
+
category: 'ai', // 'api' | 'data' | 'ai' | 'media' | 'compute' | 'storage'
|
|
1247
|
+
network: 'base', // Filter by network
|
|
1248
|
+
token: 'USDC', // Filter by token
|
|
1249
|
+
maxPrice: '0.10', // Max price in dollars
|
|
1250
|
+
query: 'image', // Search query
|
|
1251
|
+
sortBy: 'price', // 'price' | 'createdAt' | 'name'
|
|
1252
|
+
sortOrder: 'asc',
|
|
1253
|
+
});
|
|
1254
|
+
|
|
1255
|
+
for (const resource of results.resources) {
|
|
1256
|
+
console.log(`${resource.name}: ${resource.url} - $${resource.pricePerRequest}`);
|
|
1257
|
+
}
|
|
1258
|
+
```
|
|
1259
|
+
|
|
1260
|
+
### Register a Resource
|
|
1261
|
+
|
|
1262
|
+
```typescript
|
|
1263
|
+
// Registration requires API key
|
|
1264
|
+
const bazaar = new BazaarClient({
|
|
1265
|
+
apiKey: process.env.BAZAAR_API_KEY,
|
|
1266
|
+
});
|
|
1267
|
+
|
|
1268
|
+
const resource = await bazaar.register({
|
|
1269
|
+
url: 'https://api.example.com/v1/generate',
|
|
1270
|
+
name: 'AI Image Generator',
|
|
1271
|
+
description: 'Generate high-quality images with AI',
|
|
1272
|
+
category: 'ai',
|
|
1273
|
+
networks: ['base', 'ethereum', 'polygon'],
|
|
1274
|
+
tokens: ['USDC', 'EURC'],
|
|
1275
|
+
price: '0.05',
|
|
1276
|
+
payTo: '0xD3868E1eD738CED6945A574a7c769433BeD5d474',
|
|
1277
|
+
tags: ['ai', 'image', 'generator'],
|
|
1278
|
+
});
|
|
1279
|
+
|
|
1280
|
+
console.log('Registered:', resource.id);
|
|
1281
|
+
|
|
1282
|
+
// Update resource
|
|
1283
|
+
await bazaar.update(resource.id, { price: '0.03' });
|
|
1284
|
+
|
|
1285
|
+
// Deactivate (soft delete)
|
|
1286
|
+
await bazaar.deactivate(resource.id);
|
|
1287
|
+
|
|
1288
|
+
// Reactivate
|
|
1289
|
+
await bazaar.reactivate(resource.id);
|
|
1290
|
+
|
|
1291
|
+
// Delete permanently
|
|
1292
|
+
await bazaar.delete(resource.id);
|
|
1293
|
+
```
|
|
1294
|
+
|
|
1295
|
+
### List Your Resources
|
|
1296
|
+
|
|
1297
|
+
```typescript
|
|
1298
|
+
const myResources = await bazaar.listMyResources({
|
|
1299
|
+
includeInactive: true,
|
|
1300
|
+
});
|
|
1301
|
+
```
|
|
1302
|
+
|
|
1303
|
+
---
|
|
1304
|
+
|
|
1305
|
+
## Escrow & Refunds
|
|
1306
|
+
|
|
1307
|
+
For services that may require refunds, use the escrow system.
|
|
1308
|
+
|
|
1309
|
+
### Escrow Flow Diagram
|
|
1310
|
+
|
|
1311
|
+
```
|
|
1312
|
+
┌─────────────┐ ┌─────────────┐ ┌──────────────────┐ ┌──────────────┐
|
|
1313
|
+
│ Payer │ │ Your API │ │ Escrow Service │ │ Blockchain │
|
|
1314
|
+
└──────┬──────┘ └──────┬──────┘ └────────┬─────────┘ └──────┬───────┘
|
|
1315
|
+
│ │ │ │
|
|
1316
|
+
│ 1. Pay with X-PAYMENT │ │
|
|
1317
|
+
│ ────────────────> │ │ │
|
|
1318
|
+
│ │ │ │
|
|
1319
|
+
│ │ 2. Create escrow │ │
|
|
1320
|
+
│ │ ────────────────────> │
|
|
1321
|
+
│ │ │ │
|
|
1322
|
+
│ │ │ 3. Hold funds │
|
|
1323
|
+
│ │ │ ─────────────────────>
|
|
1324
|
+
│ │ │ │
|
|
1325
|
+
│ │ 4. Escrow created │ │
|
|
1326
|
+
│ │ <────────────────── │ │
|
|
1327
|
+
│ │ │ │
|
|
1328
|
+
│ 5. Provide service │ │
|
|
1329
|
+
│ <──────────────── │ │ │
|
|
1330
|
+
│ │ │ │
|
|
1331
|
+
│ ┌───────────────────────────────────────────────────────────┐
|
|
1332
|
+
│ │ IF SERVICE DELIVERED │
|
|
1333
|
+
│ └───────────────────────────────────────────────────────────┘
|
|
1334
|
+
│ │ 6a. Release escrow │ │
|
|
1335
|
+
│ │ ────────────────────> │
|
|
1336
|
+
│ │ │ │
|
|
1337
|
+
│ │ │ 7a. Transfer to │
|
|
1338
|
+
│ │ │ recipient │
|
|
1339
|
+
│ │ │ ─────────────────────>
|
|
1340
|
+
│ │ │ │
|
|
1341
|
+
│ ┌───────────────────────────────────────────────────────────┐
|
|
1342
|
+
│ │ IF SERVICE FAILED │
|
|
1343
|
+
│ └───────────────────────────────────────────────────────────┘
|
|
1344
|
+
│ 6b. Request refund│ │ │
|
|
1345
|
+
│ ────────────────> │ │ │
|
|
1346
|
+
│ │ 7b. Process refund │ │
|
|
1347
|
+
│ │ ────────────────────> │
|
|
1348
|
+
│ │ │ │
|
|
1349
|
+
│ │ │ 8b. Return to payer │
|
|
1350
|
+
│ │ │ ─────────────────────>
|
|
1351
|
+
└ └ └ └
|
|
1352
|
+
```
|
|
1353
|
+
|
|
1354
|
+
### Basic Escrow Usage
|
|
1355
|
+
|
|
1356
|
+
```typescript
|
|
1357
|
+
import {
|
|
1358
|
+
EscrowClient,
|
|
1359
|
+
canReleaseEscrow,
|
|
1360
|
+
canRefundEscrow,
|
|
1361
|
+
isEscrowExpired,
|
|
1362
|
+
} from 'uvd-x402-sdk/backend';
|
|
1363
|
+
|
|
1364
|
+
const escrow = new EscrowClient({
|
|
1365
|
+
apiKey: process.env.ESCROW_API_KEY,
|
|
1366
|
+
});
|
|
1367
|
+
|
|
1368
|
+
// Create escrow payment
|
|
1369
|
+
const escrowPayment = await escrow.createEscrow({
|
|
1370
|
+
paymentHeader: req.headers['x-payment'],
|
|
1371
|
+
requirements: paymentRequirements,
|
|
1372
|
+
escrowDuration: 86400, // 24 hours
|
|
1373
|
+
releaseConditions: {
|
|
1374
|
+
minHoldTime: 3600, // Minimum 1 hour before release
|
|
1375
|
+
},
|
|
1376
|
+
});
|
|
1377
|
+
|
|
1378
|
+
console.log('Escrow ID:', escrowPayment.id);
|
|
1379
|
+
console.log('Status:', escrowPayment.status); // 'held'
|
|
1380
|
+
|
|
1381
|
+
// Check if we can release
|
|
1382
|
+
if (canReleaseEscrow(escrowPayment)) {
|
|
1383
|
+
// After service is provided, release funds to recipient
|
|
1384
|
+
const released = await escrow.release(escrowPayment.id);
|
|
1385
|
+
console.log('Released, tx:', released.transactionHash);
|
|
1386
|
+
}
|
|
1387
|
+
```
|
|
1388
|
+
|
|
1389
|
+
### Handling Refunds
|
|
1390
|
+
|
|
1391
|
+
```typescript
|
|
1392
|
+
// Payer requests refund
|
|
1393
|
+
const refundRequest = await escrow.requestRefund({
|
|
1394
|
+
escrowId: escrowPayment.id,
|
|
1395
|
+
reason: 'Service not delivered within expected timeframe',
|
|
1396
|
+
evidence: 'Order #12345 shows pending status after 48 hours',
|
|
1397
|
+
});
|
|
1398
|
+
|
|
1399
|
+
// Recipient can approve or reject
|
|
1400
|
+
await escrow.approveRefund(refundRequest.id, refundRequest.amountRequested);
|
|
1401
|
+
// or
|
|
1402
|
+
await escrow.rejectRefund(refundRequest.id, 'Service was delivered, see tracking #XYZ');
|
|
1403
|
+
```
|
|
1404
|
+
|
|
1405
|
+
### Dispute Resolution
|
|
1406
|
+
|
|
1407
|
+
```typescript
|
|
1408
|
+
// If parties disagree, open a dispute
|
|
1409
|
+
const dispute = await escrow.openDispute(
|
|
1410
|
+
escrowPayment.id,
|
|
1411
|
+
'Service quality does not match description',
|
|
1412
|
+
'Screenshots showing issues with delivered product'
|
|
1413
|
+
);
|
|
1414
|
+
|
|
1415
|
+
// Submit additional evidence
|
|
1416
|
+
await escrow.submitEvidence(dispute.id, 'Additional documentation...');
|
|
1417
|
+
|
|
1418
|
+
// Check dispute status
|
|
1419
|
+
const updatedDispute = await escrow.getDispute(dispute.id);
|
|
1420
|
+
console.log('Outcome:', updatedDispute.outcome);
|
|
1421
|
+
// 'pending' | 'payer_wins' | 'recipient_wins' | 'split'
|
|
1422
|
+
```
|
|
1423
|
+
|
|
1424
|
+
### Helper Functions
|
|
1425
|
+
|
|
1426
|
+
```typescript
|
|
1427
|
+
import {
|
|
1428
|
+
canReleaseEscrow,
|
|
1429
|
+
canRefundEscrow,
|
|
1430
|
+
isEscrowExpired,
|
|
1431
|
+
escrowTimeRemaining,
|
|
1432
|
+
} from 'uvd-x402-sdk/backend';
|
|
1433
|
+
|
|
1434
|
+
// Check if escrow can be released
|
|
1435
|
+
if (canReleaseEscrow(escrowPayment)) {
|
|
1436
|
+
await escrow.release(escrowPayment.id);
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
// Check if escrow can be refunded
|
|
1440
|
+
if (canRefundEscrow(escrowPayment)) {
|
|
1441
|
+
await escrow.requestRefund({ escrowId: escrowPayment.id, reason: '...' });
|
|
1442
|
+
}
|
|
1443
|
+
|
|
1444
|
+
// Check expiration
|
|
1445
|
+
if (isEscrowExpired(escrowPayment)) {
|
|
1446
|
+
console.log('Escrow has expired');
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
// Time remaining
|
|
1450
|
+
const msRemaining = escrowTimeRemaining(escrowPayment);
|
|
1451
|
+
console.log(`Expires in ${msRemaining / 1000 / 60} minutes`);
|
|
1452
|
+
```
|
|
1453
|
+
|
|
1454
|
+
---
|
|
1455
|
+
|
|
1079
1456
|
## Troubleshooting
|
|
1080
1457
|
|
|
1081
1458
|
### Common Issues
|
package/dist/adapters/index.d.ts
CHANGED
package/dist/adapters/index.js
CHANGED
|
@@ -523,6 +523,80 @@ var SUPPORTED_CHAINS = {
|
|
|
523
523
|
enabled: true
|
|
524
524
|
// NEP-366 meta-transactions supported
|
|
525
525
|
}
|
|
526
|
+
},
|
|
527
|
+
// ============================================================================
|
|
528
|
+
// ALGORAND (2 networks) - Uses ASA transfers with atomic transaction groups
|
|
529
|
+
// ============================================================================
|
|
530
|
+
algorand: {
|
|
531
|
+
chainId: 0,
|
|
532
|
+
// Non-EVM (Algorand uses genesis hash for network identification)
|
|
533
|
+
chainIdHex: "0x0",
|
|
534
|
+
name: "algorand",
|
|
535
|
+
displayName: "Algorand",
|
|
536
|
+
networkType: "algorand",
|
|
537
|
+
rpcUrl: "https://mainnet-api.algonode.cloud",
|
|
538
|
+
explorerUrl: "https://allo.info",
|
|
539
|
+
nativeCurrency: {
|
|
540
|
+
name: "Algo",
|
|
541
|
+
symbol: "ALGO",
|
|
542
|
+
decimals: 6
|
|
543
|
+
// Algorand uses 6 decimals (microAlgos)
|
|
544
|
+
},
|
|
545
|
+
usdc: {
|
|
546
|
+
address: "31566704",
|
|
547
|
+
// USDC ASA ID on Algorand mainnet
|
|
548
|
+
decimals: 6,
|
|
549
|
+
name: "USDC",
|
|
550
|
+
version: "1"
|
|
551
|
+
},
|
|
552
|
+
tokens: {
|
|
553
|
+
usdc: {
|
|
554
|
+
address: "31566704",
|
|
555
|
+
// USDC ASA ID on Algorand mainnet
|
|
556
|
+
decimals: 6,
|
|
557
|
+
name: "USDC",
|
|
558
|
+
version: "1"
|
|
559
|
+
}
|
|
560
|
+
},
|
|
561
|
+
x402: {
|
|
562
|
+
facilitatorUrl: DEFAULT_FACILITATOR_URL,
|
|
563
|
+
enabled: true
|
|
564
|
+
}
|
|
565
|
+
},
|
|
566
|
+
"algorand-testnet": {
|
|
567
|
+
chainId: 0,
|
|
568
|
+
// Non-EVM
|
|
569
|
+
chainIdHex: "0x0",
|
|
570
|
+
name: "algorand-testnet",
|
|
571
|
+
displayName: "Algorand Testnet",
|
|
572
|
+
networkType: "algorand",
|
|
573
|
+
rpcUrl: "https://testnet-api.algonode.cloud",
|
|
574
|
+
explorerUrl: "https://testnet.allo.info",
|
|
575
|
+
nativeCurrency: {
|
|
576
|
+
name: "Algo",
|
|
577
|
+
symbol: "ALGO",
|
|
578
|
+
decimals: 6
|
|
579
|
+
},
|
|
580
|
+
usdc: {
|
|
581
|
+
address: "10458941",
|
|
582
|
+
// USDC ASA ID on Algorand testnet
|
|
583
|
+
decimals: 6,
|
|
584
|
+
name: "USDC",
|
|
585
|
+
version: "1"
|
|
586
|
+
},
|
|
587
|
+
tokens: {
|
|
588
|
+
usdc: {
|
|
589
|
+
address: "10458941",
|
|
590
|
+
// USDC ASA ID on Algorand testnet
|
|
591
|
+
decimals: 6,
|
|
592
|
+
name: "USDC",
|
|
593
|
+
version: "1"
|
|
594
|
+
}
|
|
595
|
+
},
|
|
596
|
+
x402: {
|
|
597
|
+
facilitatorUrl: DEFAULT_FACILITATOR_URL,
|
|
598
|
+
enabled: true
|
|
599
|
+
}
|
|
526
600
|
}
|
|
527
601
|
};
|
|
528
602
|
function getChainByName(name) {
|
|
@@ -548,7 +622,10 @@ var CAIP2_IDENTIFIERS = {
|
|
|
548
622
|
// Stellar
|
|
549
623
|
stellar: "stellar:pubnet",
|
|
550
624
|
// NEAR
|
|
551
|
-
near: "near:mainnet"
|
|
625
|
+
near: "near:mainnet",
|
|
626
|
+
// Algorand
|
|
627
|
+
algorand: "algorand:mainnet",
|
|
628
|
+
"algorand-testnet": "algorand:testnet"
|
|
552
629
|
};
|
|
553
630
|
Object.fromEntries(
|
|
554
631
|
Object.entries(CAIP2_IDENTIFIERS).map(([k, v]) => [v, k])
|
|
@@ -771,6 +848,10 @@ async function createPaymentWithResult(walletClient, options) {
|
|
|
771
848
|
return {
|
|
772
849
|
success: true,
|
|
773
850
|
paymentHeader,
|
|
851
|
+
headers: {
|
|
852
|
+
"X-PAYMENT": paymentHeader,
|
|
853
|
+
"PAYMENT-SIGNATURE": paymentHeader
|
|
854
|
+
},
|
|
774
855
|
network: options.chainName || "base",
|
|
775
856
|
payer: walletClient?.account.address
|
|
776
857
|
};
|