@paynodelabs/sdk-js 1.1.1 → 1.1.2
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/dist/client.js +5 -5
- package/dist/errors/index.d.ts +12 -13
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +12 -14
- package/dist/middleware/x402.d.ts.map +1 -1
- package/dist/middleware/x402.js +3 -2
- package/dist/utils/verifier.d.ts +2 -0
- package/dist/utils/verifier.d.ts.map +1 -1
- package/dist/utils/verifier.js +19 -13
- package/package.json +1 -1
package/dist/client.js
CHANGED
|
@@ -49,7 +49,7 @@ class PayNodeAgentClient {
|
|
|
49
49
|
catch (error) {
|
|
50
50
|
if (error instanceof errors_1.PayNodeException)
|
|
51
51
|
throw error;
|
|
52
|
-
throw new errors_1.PayNodeException(`Failed to connect to any provided RPC nodes.`, errors_1.ErrorCode.
|
|
52
|
+
throw new errors_1.PayNodeException(`Failed to connect to any provided RPC nodes.`, errors_1.ErrorCode.RpcError, error);
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
async handlePaymentAndRetry(url, options, headers) {
|
|
@@ -59,12 +59,12 @@ class PayNodeAgentClient {
|
|
|
59
59
|
const tokenAddr = headers.get('x-paynode-token-address');
|
|
60
60
|
const orderIdStr = headers.get('x-paynode-order-id');
|
|
61
61
|
if (!contractAddr || !merchantAddr || !amountStr || !tokenAddr || !orderIdStr) {
|
|
62
|
-
throw new errors_1.PayNodeException("Malformed 402 headers: missing metadata", errors_1.ErrorCode.
|
|
62
|
+
throw new errors_1.PayNodeException("Malformed 402 headers: missing metadata", errors_1.ErrorCode.InternalError);
|
|
63
63
|
}
|
|
64
64
|
const amount = BigInt(amountStr);
|
|
65
65
|
// v1.3 Constraint: Min payment protection
|
|
66
66
|
if (amount < 1000n) {
|
|
67
|
-
throw new errors_1.PayNodeException("Payment amount is below the protocol minimum (1000).", errors_1.ErrorCode.
|
|
67
|
+
throw new errors_1.PayNodeException("Payment amount is below the protocol minimum (1000).", errors_1.ErrorCode.AmountTooLow);
|
|
68
68
|
}
|
|
69
69
|
let txHash;
|
|
70
70
|
try {
|
|
@@ -74,7 +74,7 @@ class PayNodeAgentClient {
|
|
|
74
74
|
tokenContract.allowance(this.wallet.address, contractAddr)
|
|
75
75
|
]);
|
|
76
76
|
if (balance < amount) {
|
|
77
|
-
throw new errors_1.PayNodeException("Wallet lacks USDC or ETH for gas.", errors_1.ErrorCode.
|
|
77
|
+
throw new errors_1.PayNodeException("Wallet lacks USDC or ETH for gas.", errors_1.ErrorCode.InsufficientFunds);
|
|
78
78
|
}
|
|
79
79
|
// Protocol v1.3: Permit-First Execution
|
|
80
80
|
if (allowance >= amount) {
|
|
@@ -88,7 +88,7 @@ class PayNodeAgentClient {
|
|
|
88
88
|
catch (error) {
|
|
89
89
|
if (error instanceof errors_1.PayNodeException)
|
|
90
90
|
throw error;
|
|
91
|
-
throw new errors_1.PayNodeException(`On-chain transaction reverted or failed.`, errors_1.ErrorCode.
|
|
91
|
+
throw new errors_1.PayNodeException(`On-chain transaction reverted or failed.`, errors_1.ErrorCode.TransactionFailed, error);
|
|
92
92
|
}
|
|
93
93
|
console.log(`✅ [PayNode-JS] Payment confirmed on-chain: ${txHash}`);
|
|
94
94
|
const retryOptions = {
|
package/dist/errors/index.d.ts
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
export declare enum ErrorCode {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
MISSING_RECEIPT = "MISSING_RECEIPT"
|
|
2
|
+
RpcError = "RpcError",
|
|
3
|
+
InsufficientFunds = "InsufficientFunds",
|
|
4
|
+
AmountTooLow = "AmountTooLow",
|
|
5
|
+
TokenNotAccepted = "TokenNotAccepted",
|
|
6
|
+
TransactionFailed = "TransactionFailed",
|
|
7
|
+
DuplicateTransaction = "DuplicateTransaction",
|
|
8
|
+
InvalidReceipt = "InvalidReceipt",
|
|
9
|
+
InternalError = "InternalError",
|
|
10
|
+
TransactionNotFound = "TransactionNotFound",
|
|
11
|
+
WrongContract = "WrongContract",
|
|
12
|
+
OrderMismatch = "OrderMismatch",
|
|
13
|
+
MissingReceipt = "MissingReceipt"
|
|
15
14
|
}
|
|
16
15
|
export declare class PayNodeException extends Error {
|
|
17
16
|
message: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":"AAAA,oBAAY,SAAS;IACnB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":"AAAA,oBAAY,SAAS;IACnB,QAAQ,aAAa;IACrB,iBAAiB,sBAAsB;IACvC,YAAY,iBAAiB;IAC7B,gBAAgB,qBAAqB;IACrC,iBAAiB,sBAAsB;IACvC,oBAAoB,yBAAyB;IAC7C,cAAc,mBAAmB;IACjC,aAAa,kBAAkB;IAC/B,mBAAmB,wBAAwB;IAC3C,aAAa,kBAAkB;IAC/B,aAAa,kBAAkB;IAC/B,cAAc,mBAAmB;CAClC;AAED,qBAAa,gBAAiB,SAAQ,KAAK;IACtB,OAAO,EAAE,MAAM;IAAS,IAAI,EAAE,SAAS;IAAS,OAAO,CAAC,EAAE,GAAG;gBAA7D,OAAO,EAAE,MAAM,EAAS,IAAI,EAAE,SAAS,EAAS,OAAO,CAAC,EAAE,GAAG,YAAA;CAIjF"}
|
package/dist/errors/index.js
CHANGED
|
@@ -3,20 +3,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.PayNodeException = exports.ErrorCode = void 0;
|
|
4
4
|
var ErrorCode;
|
|
5
5
|
(function (ErrorCode) {
|
|
6
|
-
ErrorCode["
|
|
7
|
-
ErrorCode["
|
|
8
|
-
ErrorCode["
|
|
9
|
-
ErrorCode["
|
|
10
|
-
ErrorCode["
|
|
11
|
-
ErrorCode["
|
|
12
|
-
ErrorCode["
|
|
13
|
-
ErrorCode["
|
|
14
|
-
|
|
15
|
-
ErrorCode["
|
|
16
|
-
ErrorCode["
|
|
17
|
-
ErrorCode["
|
|
18
|
-
ErrorCode["RECEIPT_ALREADY_USED"] = "RECEIPT_ALREADY_USED";
|
|
19
|
-
ErrorCode["MISSING_RECEIPT"] = "MISSING_RECEIPT";
|
|
6
|
+
ErrorCode["RpcError"] = "RpcError";
|
|
7
|
+
ErrorCode["InsufficientFunds"] = "InsufficientFunds";
|
|
8
|
+
ErrorCode["AmountTooLow"] = "AmountTooLow";
|
|
9
|
+
ErrorCode["TokenNotAccepted"] = "TokenNotAccepted";
|
|
10
|
+
ErrorCode["TransactionFailed"] = "TransactionFailed";
|
|
11
|
+
ErrorCode["DuplicateTransaction"] = "DuplicateTransaction";
|
|
12
|
+
ErrorCode["InvalidReceipt"] = "InvalidReceipt";
|
|
13
|
+
ErrorCode["InternalError"] = "InternalError";
|
|
14
|
+
ErrorCode["TransactionNotFound"] = "TransactionNotFound";
|
|
15
|
+
ErrorCode["WrongContract"] = "WrongContract";
|
|
16
|
+
ErrorCode["OrderMismatch"] = "OrderMismatch";
|
|
17
|
+
ErrorCode["MissingReceipt"] = "MissingReceipt";
|
|
20
18
|
})(ErrorCode || (exports.ErrorCode = ErrorCode = {}));
|
|
21
19
|
class PayNodeException extends Error {
|
|
22
20
|
message;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"x402.d.ts","sourceRoot":"","sources":["../../src/middleware/x402.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAY,YAAY,EAAE,MAAM,SAAS,CAAC;AAG1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAGxD,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,KAAK,MAAM,CAAC;CAClD;AAED,eAAO,MAAM,SAAS,GAAI,SAAS,wBAAwB,
|
|
1
|
+
{"version":3,"file":"x402.d.ts","sourceRoot":"","sources":["../../src/middleware/x402.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAY,YAAY,EAAE,MAAM,SAAS,CAAC;AAG1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAGxD,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,KAAK,MAAM,CAAC;CAClD;AAED,eAAO,MAAM,SAAS,GAAI,SAAS,wBAAwB,MAiB3C,KAAK,GAAG,EAAE,KAAK,GAAG,EAAE,MAAM,YAAY,iBAwDrD,CAAC"}
|
package/dist/middleware/x402.js
CHANGED
|
@@ -8,6 +8,7 @@ const x402_gate = (options) => {
|
|
|
8
8
|
const verifier = new verifier_1.PayNodeVerifier({
|
|
9
9
|
rpcUrls: options.rpcUrls,
|
|
10
10
|
chainId: options.chainId,
|
|
11
|
+
contractAddress: options.contractAddress,
|
|
11
12
|
store: options.store
|
|
12
13
|
});
|
|
13
14
|
let rawAmount;
|
|
@@ -46,7 +47,7 @@ const x402_gate = (options) => {
|
|
|
46
47
|
}
|
|
47
48
|
return res.status(402).json({
|
|
48
49
|
error: "Payment Required",
|
|
49
|
-
code: errors_1.ErrorCode.
|
|
50
|
+
code: errors_1.ErrorCode.MissingReceipt,
|
|
50
51
|
message: "Please pay to PayNode contract and provide 'x-paynode-receipt' header.",
|
|
51
52
|
amount: options.price,
|
|
52
53
|
currency: options.currency
|
|
@@ -67,7 +68,7 @@ const x402_gate = (options) => {
|
|
|
67
68
|
else {
|
|
68
69
|
return res.status(403).json({
|
|
69
70
|
error: "Forbidden",
|
|
70
|
-
code: result.error?.code || errors_1.ErrorCode.
|
|
71
|
+
code: result.error?.code || errors_1.ErrorCode.InvalidReceipt,
|
|
71
72
|
message: result.error?.message || "Invalid receipt"
|
|
72
73
|
});
|
|
73
74
|
}
|
package/dist/utils/verifier.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export declare const ACCEPTED_TOKENS: Record<string, string[]>;
|
|
|
10
10
|
export declare const MIN_PAYMENT_AMOUNT = 1000n;
|
|
11
11
|
export interface PayNodeVerifierConfig {
|
|
12
12
|
rpcUrls: string | string[];
|
|
13
|
+
contractAddress: string;
|
|
13
14
|
chainId?: number;
|
|
14
15
|
store?: IdempotencyStore;
|
|
15
16
|
/** Override the default accepted token whitelist. If provided, only these addresses are allowed. */
|
|
@@ -23,6 +24,7 @@ export interface ExpectedPayment {
|
|
|
23
24
|
}
|
|
24
25
|
export declare class PayNodeVerifier {
|
|
25
26
|
private provider;
|
|
27
|
+
private contractAddress;
|
|
26
28
|
private chainId?;
|
|
27
29
|
private store?;
|
|
28
30
|
private acceptedTokens?;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verifier.d.ts","sourceRoot":"","sources":["../../src/utils/verifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAExD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CASpD,CAAC;AAEF,kFAAkF;AAClF,eAAO,MAAM,kBAAkB,QAAQ,CAAC;AAExC,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,oGAAoG;IACpG,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAQD,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAqC;IACrD,OAAO,CAAC,OAAO,CAAC,CAAS;IACzB,OAAO,CAAC,KAAK,CAAC,CAAmB;IACjC,OAAO,CAAC,cAAc,CAAC,CAAc;gBAEzB,MAAM,EAAE,qBAAqB;
|
|
1
|
+
{"version":3,"file":"verifier.d.ts","sourceRoot":"","sources":["../../src/utils/verifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAExD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CASpD,CAAC;AAEF,kFAAkF;AAClF,eAAO,MAAM,kBAAkB,QAAQ,CAAC;AAExC,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC3B,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,oGAAoG;IACpG,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAQD,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAqC;IACrD,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,OAAO,CAAC,CAAS;IACzB,OAAO,CAAC,KAAK,CAAC,CAAmB;IACjC,OAAO,CAAC,cAAc,CAAC,CAAc;gBAEzB,MAAM,EAAE,qBAAqB;IAmCnC,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,gBAAgB,CAAA;KAAE,CAAC;CAkFxH"}
|
package/dist/utils/verifier.js
CHANGED
|
@@ -26,12 +26,13 @@ const PAYNODE_ABI = [
|
|
|
26
26
|
const iface = new ethers_1.Interface(PAYNODE_ABI);
|
|
27
27
|
class PayNodeVerifier {
|
|
28
28
|
provider;
|
|
29
|
+
contractAddress;
|
|
29
30
|
chainId;
|
|
30
31
|
store;
|
|
31
32
|
acceptedTokens;
|
|
32
33
|
constructor(config) {
|
|
33
34
|
if (!config.rpcUrls || (Array.isArray(config.rpcUrls) && config.rpcUrls.length === 0)) {
|
|
34
|
-
throw new errors_1.PayNodeException("Failed to connect to any provided RPC nodes.", errors_1.ErrorCode.
|
|
35
|
+
throw new errors_1.PayNodeException("Failed to connect to any provided RPC nodes.", errors_1.ErrorCode.RpcError);
|
|
35
36
|
}
|
|
36
37
|
// Support RpcPool / FallbackProvider
|
|
37
38
|
if (Array.isArray(config.rpcUrls)) {
|
|
@@ -48,6 +49,7 @@ class PayNodeVerifier {
|
|
|
48
49
|
else {
|
|
49
50
|
this.provider = new ethers_1.JsonRpcProvider(config.rpcUrls, config.chainId);
|
|
50
51
|
}
|
|
52
|
+
this.contractAddress = config.contractAddress;
|
|
51
53
|
this.chainId = config.chainId;
|
|
52
54
|
this.store = config.store;
|
|
53
55
|
let tokenList;
|
|
@@ -66,31 +68,35 @@ class PayNodeVerifier {
|
|
|
66
68
|
// 0. Dust Exploit Check (Minimum Payment)
|
|
67
69
|
const expectedAmount = BigInt(expected.amount);
|
|
68
70
|
if (expectedAmount < exports.MIN_PAYMENT_AMOUNT) {
|
|
69
|
-
return { isValid: false, error: new errors_1.PayNodeException("Payment amount is below the protocol minimum (1000).", errors_1.ErrorCode.
|
|
71
|
+
return { isValid: false, error: new errors_1.PayNodeException("Payment amount is below the protocol minimum (1000).", errors_1.ErrorCode.AmountTooLow) };
|
|
70
72
|
}
|
|
71
73
|
// 1. Token Whitelist Check (Anti-FakeToken)
|
|
72
74
|
if (this.acceptedTokens && !this.acceptedTokens.has(expected.tokenAddress.toLowerCase())) {
|
|
73
|
-
return { isValid: false, error: new errors_1.PayNodeException("The provided token address is not in the whitelist.", errors_1.ErrorCode.
|
|
75
|
+
return { isValid: false, error: new errors_1.PayNodeException("The provided token address is not in the whitelist.", errors_1.ErrorCode.TokenNotAccepted) };
|
|
74
76
|
}
|
|
75
77
|
// 1. Idempotency Check
|
|
76
78
|
if (this.store) {
|
|
77
79
|
const isNew = await this.store.checkAndSet(txHash, 86400);
|
|
78
80
|
if (!isNew) {
|
|
79
|
-
return { isValid: false, error: new errors_1.PayNodeException("This transaction hash has already been consumed.", errors_1.ErrorCode.
|
|
81
|
+
return { isValid: false, error: new errors_1.PayNodeException("This transaction hash has already been consumed.", errors_1.ErrorCode.DuplicateTransaction) };
|
|
80
82
|
}
|
|
81
83
|
}
|
|
82
84
|
// 2. Fetch Receipt
|
|
83
85
|
const receipt = await this.provider.getTransactionReceipt(txHash);
|
|
84
86
|
if (!receipt) {
|
|
85
|
-
return { isValid: false, error: new errors_1.PayNodeException("The provided receipt (TxHash) is malformed or invalid.", errors_1.ErrorCode.
|
|
87
|
+
return { isValid: false, error: new errors_1.PayNodeException("The provided receipt (TxHash) is malformed or invalid.", errors_1.ErrorCode.InvalidReceipt) };
|
|
86
88
|
}
|
|
87
89
|
if (receipt.status !== 1) {
|
|
88
|
-
return { isValid: false, error: new errors_1.PayNodeException("On-chain transaction reverted or failed.", errors_1.ErrorCode.
|
|
90
|
+
return { isValid: false, error: new errors_1.PayNodeException("On-chain transaction reverted or failed.", errors_1.ErrorCode.TransactionFailed) };
|
|
89
91
|
}
|
|
90
|
-
// 3. Parse Logs
|
|
92
|
+
// 3. Parse Logs & Verify Contract Source
|
|
91
93
|
let paymentLog = null;
|
|
92
94
|
for (const log of receipt.logs) {
|
|
93
95
|
try {
|
|
96
|
+
// Security Fix: Verify the log address matches the official router address
|
|
97
|
+
if (log.address.toLowerCase() !== this.contractAddress.toLowerCase()) {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
94
100
|
const parsed = iface.parseLog({ topics: log.topics, data: log.data });
|
|
95
101
|
if (parsed && parsed.name === 'PaymentReceived') {
|
|
96
102
|
paymentLog = { parsed, logAddress: log.address };
|
|
@@ -102,32 +108,32 @@ class PayNodeVerifier {
|
|
|
102
108
|
}
|
|
103
109
|
}
|
|
104
110
|
if (!paymentLog) {
|
|
105
|
-
return { isValid: false, error: new errors_1.PayNodeException("No valid PaymentReceived event found in transaction.", errors_1.ErrorCode.
|
|
111
|
+
return { isValid: false, error: new errors_1.PayNodeException("No valid PaymentReceived event from official contract found in transaction.", errors_1.ErrorCode.WrongContract) };
|
|
106
112
|
}
|
|
107
113
|
const args = paymentLog.parsed.args;
|
|
108
114
|
// 4. Verify Merchant
|
|
109
115
|
if (args.merchant.toLowerCase() !== expected.merchantAddress.toLowerCase()) {
|
|
110
|
-
return { isValid: false, error: new errors_1.PayNodeException("Payment went to a different merchant.", errors_1.ErrorCode.
|
|
116
|
+
return { isValid: false, error: new errors_1.PayNodeException("Payment went to a different merchant.", errors_1.ErrorCode.InvalidReceipt) };
|
|
111
117
|
}
|
|
112
118
|
// 5. Verify Token
|
|
113
119
|
if (args.token.toLowerCase() !== expected.tokenAddress.toLowerCase()) {
|
|
114
|
-
return { isValid: false, error: new errors_1.PayNodeException("Payment used unexpected token.", errors_1.ErrorCode.
|
|
120
|
+
return { isValid: false, error: new errors_1.PayNodeException("Payment used unexpected token.", errors_1.ErrorCode.InvalidReceipt) };
|
|
115
121
|
}
|
|
116
122
|
// 6. Verify Amount
|
|
117
123
|
if (BigInt(args.amount) < BigInt(expected.amount)) {
|
|
118
|
-
return { isValid: false, error: new errors_1.PayNodeException("Payment amount is below required price.", errors_1.ErrorCode.
|
|
124
|
+
return { isValid: false, error: new errors_1.PayNodeException("Payment amount is below required price.", errors_1.ErrorCode.InvalidReceipt) };
|
|
119
125
|
}
|
|
120
126
|
// 7. Verify ChainId (Cross-chain replay protection)
|
|
121
127
|
const expectedChainId = BigInt(this.chainId || (await this.provider.getNetwork()).chainId);
|
|
122
128
|
if (BigInt(args.chainId) !== expectedChainId) {
|
|
123
|
-
return { isValid: false, error: new errors_1.PayNodeException("ChainId mismatch. Invalid network.", errors_1.ErrorCode.
|
|
129
|
+
return { isValid: false, error: new errors_1.PayNodeException("ChainId mismatch. Invalid network.", errors_1.ErrorCode.InvalidReceipt) };
|
|
124
130
|
}
|
|
125
131
|
return { isValid: true };
|
|
126
132
|
}
|
|
127
133
|
catch (e) {
|
|
128
134
|
if (e instanceof errors_1.PayNodeException)
|
|
129
135
|
return { isValid: false, error: e };
|
|
130
|
-
return { isValid: false, error: new errors_1.PayNodeException(`An unexpected error occurred: ${e.message}`, errors_1.ErrorCode.
|
|
136
|
+
return { isValid: false, error: new errors_1.PayNodeException(`An unexpected error occurred: ${e.message}`, errors_1.ErrorCode.InternalError) };
|
|
131
137
|
}
|
|
132
138
|
}
|
|
133
139
|
}
|