@kynesyslabs/demosdk 2.4.25 → 2.4.26
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/build/abstraction/index.d.ts +2 -2
- package/build/abstraction/index.js.map +1 -1
- package/build/d402/client/D402Client.d.ts +47 -0
- package/build/d402/client/D402Client.js +159 -0
- package/build/d402/client/D402Client.js.map +1 -0
- package/build/d402/client/index.d.ts +6 -0
- package/build/d402/client/index.js +10 -0
- package/build/d402/client/index.js.map +1 -0
- package/build/d402/client/types.d.ts +30 -0
- package/build/d402/client/types.js +7 -0
- package/build/d402/client/types.js.map +1 -0
- package/build/d402/index.d.ts +7 -0
- package/build/d402/index.js +27 -0
- package/build/d402/index.js.map +1 -0
- package/build/d402/server/D402Server.d.ts +42 -0
- package/build/d402/server/D402Server.js +156 -0
- package/build/d402/server/D402Server.js.map +1 -0
- package/build/d402/server/index.d.ts +8 -0
- package/build/d402/server/index.js +12 -0
- package/build/d402/server/index.js.map +1 -0
- package/build/d402/server/middleware.d.ts +54 -0
- package/build/d402/server/middleware.js +97 -0
- package/build/d402/server/middleware.js.map +1 -0
- package/build/d402/server/types.d.ts +49 -0
- package/build/d402/server/types.js +7 -0
- package/build/d402/server/types.js.map +1 -0
- package/package.json +5 -2
|
@@ -7,5 +7,5 @@
|
|
|
7
7
|
import { EvmCoinFinder } from "./EvmCoinFinder";
|
|
8
8
|
import { CoinFinder } from "./CoinFinder";
|
|
9
9
|
import { Identities } from "./Identities";
|
|
10
|
-
import { InferFromWritePayload, InferFromSignaturePayload, XMCoreTargetIdentityPayload, Web2CoreTargetIdentityPayload, InferFromGithubPayload, GithubProof, InferFromTwitterPayload, TwitterProof, IdentityPayload, InferFromSignatureTargetIdentityPayload, PqcIdentityAssignPayload, PqcIdentityRemovePayload, UDIdentityAssignPayload, UDIdentityRemovePayload, UserPoints, FindDemosIdByWeb2IdentityQuery, FindDemosIdByWeb3IdentityQuery, TelegramAttestationPayload, TelegramSignedAttestation } from "../types/abstraction";
|
|
11
|
-
export { EvmCoinFinder, CoinFinder, Identities, InferFromWritePayload, InferFromSignaturePayload, XMCoreTargetIdentityPayload, Web2CoreTargetIdentityPayload, InferFromGithubPayload, GithubProof, InferFromTwitterPayload, TwitterProof, IdentityPayload, InferFromSignatureTargetIdentityPayload, PqcIdentityAssignPayload, PqcIdentityRemovePayload, UDIdentityAssignPayload, UDIdentityRemovePayload, UserPoints, FindDemosIdByWeb2IdentityQuery, FindDemosIdByWeb3IdentityQuery, TelegramAttestationPayload, TelegramSignedAttestation };
|
|
10
|
+
import { InferFromWritePayload, InferFromSignaturePayload, XMCoreTargetIdentityPayload, Web2CoreTargetIdentityPayload, InferFromGithubPayload, GithubProof, InferFromTwitterPayload, TwitterProof, IdentityPayload, InferFromSignatureTargetIdentityPayload, PqcIdentityAssignPayload, PqcIdentityRemovePayload, UDIdentityAssignPayload, UDIdentityRemovePayload, UserPoints, FindDemosIdByWeb2IdentityQuery, FindDemosIdByWeb3IdentityQuery, TelegramAttestationPayload, TelegramSignedAttestation, DiscordProof } from "../types/abstraction";
|
|
11
|
+
export { EvmCoinFinder, CoinFinder, Identities, InferFromWritePayload, InferFromSignaturePayload, XMCoreTargetIdentityPayload, Web2CoreTargetIdentityPayload, InferFromGithubPayload, GithubProof, InferFromTwitterPayload, TwitterProof, IdentityPayload, InferFromSignatureTargetIdentityPayload, PqcIdentityAssignPayload, PqcIdentityRemovePayload, UDIdentityAssignPayload, UDIdentityRemovePayload, UserPoints, FindDemosIdByWeb2IdentityQuery, FindDemosIdByWeb3IdentityQuery, TelegramAttestationPayload, TelegramSignedAttestation, DiscordProof };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/abstraction/index.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEH,mDAA+C;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/abstraction/index.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEH,mDAA+C;AA2B3C,8FA3BK,6BAAa,OA2BL;AA1BjB,6CAAyC;AA2BrC,2FA3BK,uBAAU,OA2BL;AA1Bd,6CAAyC;AA2BrC,2FA3BK,uBAAU,OA2BL"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* D402Client - Client-side HTTP 402 payment protocol implementation
|
|
3
|
+
*
|
|
4
|
+
* Handles payment creation and settlement for 402 responses.
|
|
5
|
+
*/
|
|
6
|
+
import type { Demos } from '../../websdk/demosclass';
|
|
7
|
+
import type { Transaction } from '../../types';
|
|
8
|
+
import type { D402PaymentRequirement, D402SettlementResult } from './types';
|
|
9
|
+
export declare class D402Client {
|
|
10
|
+
private demos;
|
|
11
|
+
constructor(demos: Demos);
|
|
12
|
+
/**
|
|
13
|
+
* Create a d402_payment transaction from 402 response requirements
|
|
14
|
+
* @param requirement Payment requirements from 402 response
|
|
15
|
+
* @returns Unsigned d402_payment transaction
|
|
16
|
+
*/
|
|
17
|
+
createPayment(requirement: D402PaymentRequirement): Promise<Transaction>;
|
|
18
|
+
/**
|
|
19
|
+
* Sign and broadcast a d402_payment transaction
|
|
20
|
+
* @param payment Unsigned payment transaction from createPayment()
|
|
21
|
+
* @returns Settlement result with transaction hash
|
|
22
|
+
*/
|
|
23
|
+
settle(payment: Transaction): Promise<D402SettlementResult>;
|
|
24
|
+
/**
|
|
25
|
+
* Complete payment flow for a 402 response
|
|
26
|
+
* Handles payment creation, settlement, and retry with payment proof
|
|
27
|
+
*
|
|
28
|
+
* @param requirement Payment requirements from 402 response
|
|
29
|
+
* @param url Original URL that returned 402
|
|
30
|
+
* @param requestInit Original fetch options
|
|
31
|
+
* @returns Final response after payment
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```typescript
|
|
35
|
+
* const response = await fetch('/premium')
|
|
36
|
+
* if (response.status === 402) {
|
|
37
|
+
* const requirement = await response.json()
|
|
38
|
+
* const finalResponse = await d402.handlePaymentRequired(
|
|
39
|
+
* requirement,
|
|
40
|
+
* '/premium',
|
|
41
|
+
* { method: 'GET' }
|
|
42
|
+
* )
|
|
43
|
+
* }
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
handlePaymentRequired(requirement: D402PaymentRequirement, url: string, requestInit?: RequestInit): Promise<Response>;
|
|
47
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* D402Client - Client-side HTTP 402 payment protocol implementation
|
|
4
|
+
*
|
|
5
|
+
* Handles payment creation and settlement for 402 responses.
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.D402Client = void 0;
|
|
42
|
+
const unifiedCrypto_1 = require("../../encryption/unifiedCrypto");
|
|
43
|
+
const skeletons = __importStar(require("../../websdk/utils/skeletons"));
|
|
44
|
+
class D402Client {
|
|
45
|
+
constructor(demos) {
|
|
46
|
+
``;
|
|
47
|
+
this.demos = demos;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Create a d402_payment transaction from 402 response requirements
|
|
51
|
+
* @param requirement Payment requirements from 402 response
|
|
52
|
+
* @returns Unsigned d402_payment transaction
|
|
53
|
+
*/
|
|
54
|
+
async createPayment(requirement) {
|
|
55
|
+
if (!this.demos.keypair) {
|
|
56
|
+
throw new Error('Wallet not connected');
|
|
57
|
+
}
|
|
58
|
+
// Get user's public key and nonce
|
|
59
|
+
const { publicKey } = await this.demos.crypto.getIdentity('ed25519');
|
|
60
|
+
const publicKeyHex = (0, unifiedCrypto_1.uint8ArrayToHex)(publicKey);
|
|
61
|
+
const nonce = await this.demos.getAddressNonce(publicKeyHex);
|
|
62
|
+
// Create transaction skeleton
|
|
63
|
+
const tx = structuredClone(skeletons.transaction);
|
|
64
|
+
// Build memo with resource ID
|
|
65
|
+
const memo = requirement.description
|
|
66
|
+
? `resourceId:${requirement.resourceId} - ${requirement.description}`
|
|
67
|
+
: `resourceId:${requirement.resourceId}`;
|
|
68
|
+
// Fill in transaction details
|
|
69
|
+
tx.content.type = 'd402_payment';
|
|
70
|
+
tx.content.nonce = nonce + 1;
|
|
71
|
+
tx.content.timestamp = Date.now();
|
|
72
|
+
tx.content.data = [
|
|
73
|
+
'd402_payment',
|
|
74
|
+
{
|
|
75
|
+
to: requirement.recipient,
|
|
76
|
+
amount: requirement.amount,
|
|
77
|
+
memo: memo
|
|
78
|
+
}
|
|
79
|
+
];
|
|
80
|
+
return tx;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Sign and broadcast a d402_payment transaction
|
|
84
|
+
* @param payment Unsigned payment transaction from createPayment()
|
|
85
|
+
* @returns Settlement result with transaction hash
|
|
86
|
+
*/
|
|
87
|
+
async settle(payment) {
|
|
88
|
+
try {
|
|
89
|
+
// Sign the transaction
|
|
90
|
+
const signedTx = await this.demos.sign(payment);
|
|
91
|
+
// Broadcast to network via RPC
|
|
92
|
+
const result = await this.demos.nodeCall('broadcastNativeTransaction', {
|
|
93
|
+
transaction: signedTx
|
|
94
|
+
});
|
|
95
|
+
if (result.success) {
|
|
96
|
+
return {
|
|
97
|
+
success: true,
|
|
98
|
+
hash: signedTx.hash,
|
|
99
|
+
blockNumber: result.blockNumber
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
return {
|
|
104
|
+
success: false,
|
|
105
|
+
hash: signedTx.hash,
|
|
106
|
+
message: result.message || 'Settlement failed'
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
return {
|
|
112
|
+
success: false,
|
|
113
|
+
hash: '',
|
|
114
|
+
message: error.message || 'Settlement error'
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Complete payment flow for a 402 response
|
|
120
|
+
* Handles payment creation, settlement, and retry with payment proof
|
|
121
|
+
*
|
|
122
|
+
* @param requirement Payment requirements from 402 response
|
|
123
|
+
* @param url Original URL that returned 402
|
|
124
|
+
* @param requestInit Original fetch options
|
|
125
|
+
* @returns Final response after payment
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```typescript
|
|
129
|
+
* const response = await fetch('/premium')
|
|
130
|
+
* if (response.status === 402) {
|
|
131
|
+
* const requirement = await response.json()
|
|
132
|
+
* const finalResponse = await d402.handlePaymentRequired(
|
|
133
|
+
* requirement,
|
|
134
|
+
* '/premium',
|
|
135
|
+
* { method: 'GET' }
|
|
136
|
+
* )
|
|
137
|
+
* }
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
async handlePaymentRequired(requirement, url, requestInit) {
|
|
141
|
+
// Create payment
|
|
142
|
+
const payment = await this.createPayment(requirement);
|
|
143
|
+
// Settle payment
|
|
144
|
+
const result = await this.settle(payment);
|
|
145
|
+
if (!result.success) {
|
|
146
|
+
throw new Error(`Payment failed: ${result.message}`);
|
|
147
|
+
}
|
|
148
|
+
// Retry original request with payment proof header
|
|
149
|
+
const headers = new Headers(requestInit?.headers || {});
|
|
150
|
+
headers.set('X-Payment-Proof', result.hash);
|
|
151
|
+
const retryResponse = await fetch(url, {
|
|
152
|
+
...requestInit,
|
|
153
|
+
headers: headers
|
|
154
|
+
});
|
|
155
|
+
return retryResponse;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
exports.D402Client = D402Client;
|
|
159
|
+
//# sourceMappingURL=D402Client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"D402Client.js","sourceRoot":"","sources":["../../../../src/d402/client/D402Client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* D402 Client Module
|
|
4
|
+
* Client-side utilities for HTTP 402 payment protocol
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.D402Client = void 0;
|
|
8
|
+
var D402Client_1 = require("./D402Client");
|
|
9
|
+
Object.defineProperty(exports, "D402Client", { enumerable: true, get: function () { return D402Client_1.D402Client; } });
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/d402/client/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,2CAAyC;AAAhC,wGAAA,UAAU,OAAA"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* D402 Client Types
|
|
3
|
+
* Client-side types for HTTP 402 payment protocol implementation
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Payment requirement from 402 response
|
|
7
|
+
*/
|
|
8
|
+
export interface D402PaymentRequirement {
|
|
9
|
+
/** Payment amount in smallest unit */
|
|
10
|
+
amount: number;
|
|
11
|
+
/** Merchant/recipient address */
|
|
12
|
+
recipient: string;
|
|
13
|
+
/** Resource identifier */
|
|
14
|
+
resourceId: string;
|
|
15
|
+
/** Optional description */
|
|
16
|
+
description?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Payment settlement result
|
|
20
|
+
*/
|
|
21
|
+
export interface D402SettlementResult {
|
|
22
|
+
/** Whether settlement succeeded */
|
|
23
|
+
success: boolean;
|
|
24
|
+
/** Transaction hash (payment proof) */
|
|
25
|
+
hash: string;
|
|
26
|
+
/** Block number (if settled) */
|
|
27
|
+
blockNumber?: number;
|
|
28
|
+
/** Error message (if failed) */
|
|
29
|
+
message?: string;
|
|
30
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/d402/client/types.ts"],"names":[],"mappings":";AAAA;;;GAGG"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* D402 Payment Protocol Module
|
|
4
|
+
* HTTP 402 payment implementation for Demos Network
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
18
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
19
|
+
};
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.D402Client = void 0;
|
|
22
|
+
// Export server module
|
|
23
|
+
__exportStar(require("./server"), exports);
|
|
24
|
+
// Export client module (explicit exports to avoid conflicts)
|
|
25
|
+
var client_1 = require("./client");
|
|
26
|
+
Object.defineProperty(exports, "D402Client", { enumerable: true, get: function () { return client_1.D402Client; } });
|
|
27
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/d402/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;AAEH,uBAAuB;AACvB,2CAAwB;AAExB,6DAA6D;AAC7D,mCAAqC;AAA5B,oGAAA,UAAU,OAAA"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* D402Server - Server-side HTTP 402 payment protocol implementation
|
|
3
|
+
*
|
|
4
|
+
* Handles payment verification and content gating for Demos Network applications.
|
|
5
|
+
*/
|
|
6
|
+
import type { D402ServerConfig, D402PaymentRequirement, D402VerificationResult } from './types';
|
|
7
|
+
export declare class D402Server {
|
|
8
|
+
private rpcUrl;
|
|
9
|
+
private cacheTTL;
|
|
10
|
+
private paymentCache;
|
|
11
|
+
constructor(config: D402ServerConfig);
|
|
12
|
+
/**
|
|
13
|
+
* Verify a payment transaction via RPC
|
|
14
|
+
* @param txHash Transaction hash from X-Payment-Proof header
|
|
15
|
+
* @returns Verification result with payment details
|
|
16
|
+
*/
|
|
17
|
+
verify(txHash: string): Promise<D402VerificationResult>;
|
|
18
|
+
/**
|
|
19
|
+
* Generate HTTP 402 Payment Required response data
|
|
20
|
+
* @param requirement Payment requirements
|
|
21
|
+
* @returns 402 response object
|
|
22
|
+
*/
|
|
23
|
+
require(requirement: D402PaymentRequirement): {
|
|
24
|
+
status: 402;
|
|
25
|
+
body: D402PaymentRequirement;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Validate that a payment matches the requirements
|
|
29
|
+
* @param verification Verification result from verify()
|
|
30
|
+
* @param requirement Original payment requirements
|
|
31
|
+
* @returns True if payment is valid for the resource
|
|
32
|
+
*/
|
|
33
|
+
validatePayment(verification: D402VerificationResult, requirement: D402PaymentRequirement): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Clear expired entries from payment cache
|
|
36
|
+
*/
|
|
37
|
+
private cleanCache;
|
|
38
|
+
/**
|
|
39
|
+
* Manually clear the entire payment cache
|
|
40
|
+
*/
|
|
41
|
+
clearCache(): void;
|
|
42
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* D402Server - Server-side HTTP 402 payment protocol implementation
|
|
4
|
+
*
|
|
5
|
+
* Handles payment verification and content gating for Demos Network applications.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.D402Server = void 0;
|
|
9
|
+
class D402Server {
|
|
10
|
+
constructor(config) {
|
|
11
|
+
this.rpcUrl = config.rpcUrl;
|
|
12
|
+
this.cacheTTL = config.cacheTTL || 300; // Default 5 minutes
|
|
13
|
+
this.paymentCache = new Map();
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Verify a payment transaction via RPC
|
|
17
|
+
* @param txHash Transaction hash from X-Payment-Proof header
|
|
18
|
+
* @returns Verification result with payment details
|
|
19
|
+
*/
|
|
20
|
+
async verify(txHash) {
|
|
21
|
+
// Check cache first
|
|
22
|
+
const cached = this.paymentCache.get(txHash);
|
|
23
|
+
if (cached && Date.now() < cached.expiresAt) {
|
|
24
|
+
return {
|
|
25
|
+
valid: true,
|
|
26
|
+
verified_from: cached.from,
|
|
27
|
+
verified_to: cached.to,
|
|
28
|
+
verified_amount: cached.amount,
|
|
29
|
+
verified_memo: cached.memo,
|
|
30
|
+
timestamp: cached.timestamp
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
// Fetch transaction from RPC
|
|
34
|
+
// Note: We need to get the full transaction, not just verify
|
|
35
|
+
// The /d402/verify endpoint expects a full transaction object
|
|
36
|
+
// So we'll fetch the transaction first, then verify it
|
|
37
|
+
try {
|
|
38
|
+
const txResponse = await fetch(`${this.rpcUrl}/getTransaction`, {
|
|
39
|
+
method: 'POST',
|
|
40
|
+
headers: { 'Content-Type': 'application/json' },
|
|
41
|
+
body: JSON.stringify({ hash: txHash })
|
|
42
|
+
});
|
|
43
|
+
if (!txResponse.ok) {
|
|
44
|
+
return {
|
|
45
|
+
valid: false,
|
|
46
|
+
timestamp: Date.now()
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
const tx = await txResponse.json();
|
|
50
|
+
// Verify the transaction
|
|
51
|
+
const verifyResponse = await fetch(`${this.rpcUrl}/d402/verify`, {
|
|
52
|
+
method: 'POST',
|
|
53
|
+
headers: { 'Content-Type': 'application/json' },
|
|
54
|
+
body: JSON.stringify({ transaction: tx })
|
|
55
|
+
});
|
|
56
|
+
if (!verifyResponse.ok) {
|
|
57
|
+
return {
|
|
58
|
+
valid: false,
|
|
59
|
+
timestamp: Date.now()
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
const verification = await verifyResponse.json();
|
|
63
|
+
if (verification.valid) {
|
|
64
|
+
// Extract payment details from transaction
|
|
65
|
+
const paymentData = tx.content.data[1];
|
|
66
|
+
const memo = paymentData.memo || '';
|
|
67
|
+
// Cache the verified payment
|
|
68
|
+
const cachedPayment = {
|
|
69
|
+
txHash,
|
|
70
|
+
from: verification.verified_from,
|
|
71
|
+
to: verification.verified_to,
|
|
72
|
+
amount: verification.verified_amount,
|
|
73
|
+
memo,
|
|
74
|
+
timestamp: verification.timestamp,
|
|
75
|
+
expiresAt: Date.now() + (this.cacheTTL * 1000)
|
|
76
|
+
};
|
|
77
|
+
this.paymentCache.set(txHash, cachedPayment);
|
|
78
|
+
return {
|
|
79
|
+
valid: true,
|
|
80
|
+
verified_from: verification.verified_from,
|
|
81
|
+
verified_to: verification.verified_to,
|
|
82
|
+
verified_amount: verification.verified_amount,
|
|
83
|
+
verified_memo: memo,
|
|
84
|
+
timestamp: verification.timestamp
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
valid: false,
|
|
89
|
+
timestamp: Date.now()
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
console.error('D402Server: Verification error:', error);
|
|
94
|
+
return {
|
|
95
|
+
valid: false,
|
|
96
|
+
timestamp: Date.now()
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Generate HTTP 402 Payment Required response data
|
|
102
|
+
* @param requirement Payment requirements
|
|
103
|
+
* @returns 402 response object
|
|
104
|
+
*/
|
|
105
|
+
require(requirement) {
|
|
106
|
+
return {
|
|
107
|
+
status: 402,
|
|
108
|
+
body: requirement
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Validate that a payment matches the requirements
|
|
113
|
+
* @param verification Verification result from verify()
|
|
114
|
+
* @param requirement Original payment requirements
|
|
115
|
+
* @returns True if payment is valid for the resource
|
|
116
|
+
*/
|
|
117
|
+
validatePayment(verification, requirement) {
|
|
118
|
+
if (!verification.valid) {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
// Check recipient matches
|
|
122
|
+
if (verification.verified_to !== requirement.recipient) {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
// Check amount matches (or exceeds)
|
|
126
|
+
if (verification.verified_amount < requirement.amount) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
// Check resource ID in memo (format: "resourceId:xyz")
|
|
130
|
+
const memo = verification.verified_memo || '';
|
|
131
|
+
const expectedMemoPrefix = `resourceId:${requirement.resourceId}`;
|
|
132
|
+
if (!memo.startsWith(expectedMemoPrefix)) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Clear expired entries from payment cache
|
|
139
|
+
*/
|
|
140
|
+
cleanCache() {
|
|
141
|
+
const now = Date.now();
|
|
142
|
+
for (const [hash, payment] of this.paymentCache.entries()) {
|
|
143
|
+
if (now >= payment.expiresAt) {
|
|
144
|
+
this.paymentCache.delete(hash);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Manually clear the entire payment cache
|
|
150
|
+
*/
|
|
151
|
+
clearCache() {
|
|
152
|
+
this.paymentCache.clear();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
exports.D402Server = D402Server;
|
|
156
|
+
//# sourceMappingURL=D402Server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"D402Server.js","sourceRoot":"","sources":["../../../../src/d402/server/D402Server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* D402 Server Module
|
|
3
|
+
* Server-side utilities for HTTP 402 payment protocol
|
|
4
|
+
*/
|
|
5
|
+
export { D402Server } from './D402Server';
|
|
6
|
+
export { d402Required } from './middleware';
|
|
7
|
+
export type { D402ServerConfig, D402PaymentRequirement, D402VerificationResult, CachedPayment } from './types';
|
|
8
|
+
export type { D402MiddlewareOptions, D402Request } from './middleware';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* D402 Server Module
|
|
4
|
+
* Server-side utilities for HTTP 402 payment protocol
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.d402Required = exports.D402Server = void 0;
|
|
8
|
+
var D402Server_1 = require("./D402Server");
|
|
9
|
+
Object.defineProperty(exports, "D402Server", { enumerable: true, get: function () { return D402Server_1.D402Server; } });
|
|
10
|
+
var middleware_1 = require("./middleware");
|
|
11
|
+
Object.defineProperty(exports, "d402Required", { enumerable: true, get: function () { return middleware_1.d402Required; } });
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/d402/server/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,2CAAyC;AAAhC,wGAAA,UAAU,OAAA;AACnB,2CAA2C;AAAlC,0GAAA,YAAY,OAAA"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* D402 Express Middleware
|
|
3
|
+
* Express-compatible middleware for HTTP 402 payment gating
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Middleware configuration options
|
|
7
|
+
*/
|
|
8
|
+
export interface D402MiddlewareOptions {
|
|
9
|
+
/** Payment amount in smallest unit */
|
|
10
|
+
amount: number;
|
|
11
|
+
/** Resource identifier (included in memo validation) */
|
|
12
|
+
resourceId: string;
|
|
13
|
+
/** Demos Network RPC URL */
|
|
14
|
+
rpcUrl: string;
|
|
15
|
+
/** Merchant/recipient address (if not provided, must be in req.d402Recipient) */
|
|
16
|
+
recipient?: string;
|
|
17
|
+
/** Optional payment description */
|
|
18
|
+
description?: string;
|
|
19
|
+
/** Payment cache TTL in seconds (default: 300) */
|
|
20
|
+
cacheTTL?: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Express Request with D402 extensions
|
|
24
|
+
*/
|
|
25
|
+
export interface D402Request {
|
|
26
|
+
/** Merchant address (can be set dynamically per request) */
|
|
27
|
+
d402Recipient?: string;
|
|
28
|
+
/** Verified payment details (available after middleware passes) */
|
|
29
|
+
d402Payment?: {
|
|
30
|
+
from: string;
|
|
31
|
+
to: string;
|
|
32
|
+
amount: number;
|
|
33
|
+
txHash: string;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Create Express middleware for D402 payment gating
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* app.get('/premium-article',
|
|
42
|
+
* d402Required({
|
|
43
|
+
* amount: 5000000000000000000, // 5 DEM in smallest unit
|
|
44
|
+
* resourceId: 'article-123',
|
|
45
|
+
* rpcUrl: 'https://node2.demos.sh',
|
|
46
|
+
* recipient: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb'
|
|
47
|
+
* }),
|
|
48
|
+
* (req, res) => {
|
|
49
|
+
* res.json({ article: "Premium content" })
|
|
50
|
+
* }
|
|
51
|
+
* )
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export declare function d402Required(options: D402MiddlewareOptions): (req: any, res: any, next: any) => Promise<any>;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* D402 Express Middleware
|
|
4
|
+
* Express-compatible middleware for HTTP 402 payment gating
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.d402Required = d402Required;
|
|
8
|
+
const D402Server_1 = require("./D402Server");
|
|
9
|
+
/**
|
|
10
|
+
* Create Express middleware for D402 payment gating
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* app.get('/premium-article',
|
|
15
|
+
* d402Required({
|
|
16
|
+
* amount: 5000000000000000000, // 5 DEM in smallest unit
|
|
17
|
+
* resourceId: 'article-123',
|
|
18
|
+
* rpcUrl: 'https://node2.demos.sh',
|
|
19
|
+
* recipient: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb'
|
|
20
|
+
* }),
|
|
21
|
+
* (req, res) => {
|
|
22
|
+
* res.json({ article: "Premium content" })
|
|
23
|
+
* }
|
|
24
|
+
* )
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
function d402Required(options) {
|
|
28
|
+
const server = new D402Server_1.D402Server({
|
|
29
|
+
rpcUrl: options.rpcUrl,
|
|
30
|
+
cacheTTL: options.cacheTTL
|
|
31
|
+
});
|
|
32
|
+
return async (req, res, next) => {
|
|
33
|
+
try {
|
|
34
|
+
// Get payment proof from header
|
|
35
|
+
const paymentProof = req.headers['x-payment-proof'];
|
|
36
|
+
// Determine recipient address
|
|
37
|
+
const recipient = options.recipient || req.d402Recipient;
|
|
38
|
+
if (!recipient) {
|
|
39
|
+
return res.status(500).json({
|
|
40
|
+
error: 'Server misconfiguration: recipient address not provided'
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
// If no payment proof, return 402 with requirements
|
|
44
|
+
if (!paymentProof) {
|
|
45
|
+
const requirement = {
|
|
46
|
+
amount: options.amount,
|
|
47
|
+
recipient: recipient,
|
|
48
|
+
resourceId: options.resourceId,
|
|
49
|
+
description: options.description
|
|
50
|
+
};
|
|
51
|
+
const response = server.require(requirement);
|
|
52
|
+
return res.status(response.status).json(response.body);
|
|
53
|
+
}
|
|
54
|
+
// Verify payment
|
|
55
|
+
const verification = await server.verify(paymentProof);
|
|
56
|
+
if (!verification.valid) {
|
|
57
|
+
return res.status(403).json({
|
|
58
|
+
error: 'Invalid payment proof'
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
// Validate payment matches requirements
|
|
62
|
+
const requirement = {
|
|
63
|
+
amount: options.amount,
|
|
64
|
+
recipient: recipient,
|
|
65
|
+
resourceId: options.resourceId,
|
|
66
|
+
description: options.description
|
|
67
|
+
};
|
|
68
|
+
const isValid = server.validatePayment(verification, requirement);
|
|
69
|
+
if (!isValid) {
|
|
70
|
+
return res.status(403).json({
|
|
71
|
+
error: 'Payment does not match requirements',
|
|
72
|
+
details: {
|
|
73
|
+
expected_recipient: recipient,
|
|
74
|
+
expected_amount: options.amount,
|
|
75
|
+
expected_resource: `resourceId:${options.resourceId}`
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
// Attach payment details to request for downstream handlers
|
|
80
|
+
req.d402Payment = {
|
|
81
|
+
from: verification.verified_from,
|
|
82
|
+
to: verification.verified_to,
|
|
83
|
+
amount: verification.verified_amount,
|
|
84
|
+
txHash: paymentProof
|
|
85
|
+
};
|
|
86
|
+
// Payment valid, proceed
|
|
87
|
+
next();
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
console.error('D402 middleware error:', error);
|
|
91
|
+
return res.status(500).json({
|
|
92
|
+
error: 'Payment verification failed'
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../../../src/d402/server/middleware.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* D402 Server Types
|
|
3
|
+
* Server-side types for HTTP 402 payment protocol implementation
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Payment requirements sent in 402 response
|
|
7
|
+
*/
|
|
8
|
+
export interface D402PaymentRequirement {
|
|
9
|
+
/** Payment amount in smallest unit */
|
|
10
|
+
amount: number;
|
|
11
|
+
/** Merchant/recipient address */
|
|
12
|
+
recipient: string;
|
|
13
|
+
/** Resource identifier (used in memo validation) */
|
|
14
|
+
resourceId: string;
|
|
15
|
+
/** Optional payment description */
|
|
16
|
+
description?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Payment verification result from RPC
|
|
20
|
+
*/
|
|
21
|
+
export interface D402VerificationResult {
|
|
22
|
+
valid: boolean;
|
|
23
|
+
verified_from?: string;
|
|
24
|
+
verified_to?: string;
|
|
25
|
+
verified_amount?: number;
|
|
26
|
+
verified_memo?: string;
|
|
27
|
+
timestamp: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* D402Server configuration options
|
|
31
|
+
*/
|
|
32
|
+
export interface D402ServerConfig {
|
|
33
|
+
/** Demos Network RPC URL */
|
|
34
|
+
rpcUrl: string;
|
|
35
|
+
/** Payment cache TTL in seconds (default: 300 = 5 minutes) */
|
|
36
|
+
cacheTTL?: number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Cached payment data
|
|
40
|
+
*/
|
|
41
|
+
export interface CachedPayment {
|
|
42
|
+
txHash: string;
|
|
43
|
+
from: string;
|
|
44
|
+
to: string;
|
|
45
|
+
amount: number;
|
|
46
|
+
memo: string;
|
|
47
|
+
timestamp: number;
|
|
48
|
+
expiresAt: number;
|
|
49
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/d402/server/types.ts"],"names":[],"mappings":";AAAA;;;GAGG"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kynesyslabs/demosdk",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.26",
|
|
4
4
|
"description": "Demosdk is a JavaScript/TypeScript SDK that provides a unified interface for interacting with Demos network",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -33,7 +33,10 @@
|
|
|
33
33
|
"./utils": "./build/utils/index.js",
|
|
34
34
|
"./encryption": "./build/encryption/index.js",
|
|
35
35
|
"./bridge": "./build/bridge/index.js",
|
|
36
|
-
"./storage": "./build/storage/index.js"
|
|
36
|
+
"./storage": "./build/storage/index.js",
|
|
37
|
+
"./d402": "./build/d402/index.js",
|
|
38
|
+
"./d402/server": "./build/d402/server/index.js",
|
|
39
|
+
"./d402/client": "./build/d402/client/index.js"
|
|
37
40
|
},
|
|
38
41
|
"scripts": {
|
|
39
42
|
"postinstall": "cp .github/hooks/pre-commit .git/hooks/pre-commit 2>/dev/null && chmod +x .git/hooks/pre-commit 2>/dev/null || true",
|