@xfuel/verify 0.1.0 → 0.2.1
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 +44 -8
- package/dist/base-payer.d.ts +65 -0
- package/dist/base-payer.d.ts.map +1 -0
- package/dist/base-payer.js +222 -0
- package/dist/base-payer.js.map +1 -0
- package/dist/cli.js +93 -11
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +185 -48
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +744 -85
- package/dist/index.js.map +1 -1
- package/dist/jws.d.ts +46 -0
- package/dist/jws.d.ts.map +1 -0
- package/dist/jws.js +129 -0
- package/dist/jws.js.map +1 -0
- package/dist/payer.d.ts +65 -0
- package/dist/payer.d.ts.map +1 -0
- package/dist/payer.js +148 -0
- package/dist/payer.js.map +1 -0
- package/dist/solana-payer.d.ts +99 -0
- package/dist/solana-payer.d.ts.map +1 -0
- package/dist/solana-payer.js +258 -0
- package/dist/solana-payer.js.map +1 -0
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -40,7 +40,7 @@ npx xfuel-verify receipt.json --check-nullifier
|
|
|
40
40
|
npx xfuel-verify receipt.json --json
|
|
41
41
|
|
|
42
42
|
# From stdin
|
|
43
|
-
curl -s https://api.
|
|
43
|
+
curl -s https://api.chit402.com/receipt/task-123?format=json | npx xfuel-verify -
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
## What This Verifies
|
|
@@ -48,24 +48,60 @@ curl -s https://api.xfuel.app/receipt/task-123?format=json | npx xfuel-verify -
|
|
|
48
48
|
| Check | Requires Network? | Description |
|
|
49
49
|
|-------|-------------------|-------------|
|
|
50
50
|
| Payment binding | No | Recompute commitment from receipt fields |
|
|
51
|
-
| Issuer signature | No | ES256
|
|
51
|
+
| Issuer signature | No, unless `--fetch-jwks` | ES256. Trusted only via JWKS (by kid) or a pinned RFC 7638 kid |
|
|
52
52
|
| Output hash | No | Hash is on the receipt |
|
|
53
53
|
| On-chain settlement | Yes | Query Base RPC for tx |
|
|
54
54
|
| Nullifier anchor | Yes | Query ZKVerifierSP1 contract |
|
|
55
55
|
|
|
56
|
-
## Issuer Signature Verification (ES256
|
|
56
|
+
## Issuer Signature Verification (ES256)
|
|
57
57
|
|
|
58
|
-
Receipts
|
|
58
|
+
Receipts include `issuer_signature.jws` (compact ES256 / P-256). The signature
|
|
59
|
+
counts only when the verifying key is trusted:
|
|
60
|
+
|
|
61
|
+
1. **JWKS by kid** — a key in `--jwks-file`, `--jwks-url`, or `--fetch-jwks`
|
|
62
|
+
(allowlisted host, default `api.chit402.com`) whose `kid` matches the JWS.
|
|
63
|
+
2. **Pinned thumbprint** — the embedded `issuer_jwk` is used only when its
|
|
64
|
+
RFC 7638 thumbprint equals a trusted kid. The default offline pin is the
|
|
65
|
+
production kid `IvFpmC-vPhkY_v0vidsrWVT9uzlE5XWKZgAEOeJTq1Q`. Override with
|
|
66
|
+
`--trusted-kid`, or disable with `--no-trusted-kid`.
|
|
67
|
+
|
|
68
|
+
`issuer_jwk` on the receipt is not a trust root. A copy re-signed with an
|
|
69
|
+
arbitrary P-256 key reports `key untrusted` (`issuer_signature.valid === false`),
|
|
70
|
+
including when `--jwks-file` points at the real JWKS.
|
|
59
71
|
|
|
60
72
|
```bash
|
|
61
|
-
#
|
|
73
|
+
# Offline: default production pin, no network
|
|
74
|
+
npx xfuel-verify receipt.json
|
|
75
|
+
|
|
76
|
+
# Trust the published JWKS instead of (or in addition to) the pin
|
|
62
77
|
curl -o issuer-jwks.json https://api.chit402.com/.well-known/jwks.json
|
|
78
|
+
npx xfuel-verify receipt.json --jwks-file issuer-jwks.json --no-trusted-kid
|
|
79
|
+
|
|
80
|
+
# Fetch the issuer JWKS (https://api.chit402.com/.well-known/jwks.json)
|
|
81
|
+
npx xfuel-verify receipt.json --fetch-jwks
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import { verifyReceipt } from '@xfuel/verify';
|
|
63
86
|
|
|
64
|
-
|
|
65
|
-
|
|
87
|
+
const result = await verifyReceipt(receipt);
|
|
88
|
+
console.log(result.issuer_signature.valid); // true only for a trusted key
|
|
89
|
+
console.log(result.issuer_signature.key_trusted);
|
|
90
|
+
console.log(result.amount_usdc); // from verified claims, not the outer copy
|
|
91
|
+
console.log(result.claim_mismatches); // outer payment / caller_binding vs JWS
|
|
66
92
|
```
|
|
67
93
|
|
|
68
|
-
|
|
94
|
+
Amount, payer, payee, asset, and tx are read from the verified JWS claims.
|
|
95
|
+
If the unsigned outer `payment` or `caller_binding` disagrees, verification
|
|
96
|
+
fails. `--check-payer` on Base confirms payer, payee, asset, and amount in the
|
|
97
|
+
USDC `Transfer` log.
|
|
98
|
+
|
|
99
|
+
A paid USDC receipt whose signed `binding.expected_commitment` is null is
|
|
100
|
+
reported as “No payment-binding commitment”, not as an unmetered or TFUEL receipt.
|
|
101
|
+
|
|
102
|
+
The CLI does **not** fetch JWKS unless `--fetch-jwks` or `--jwks-url` is set.
|
|
103
|
+
Exit code 1 is returned when the key is untrusted, the signature is invalid, or
|
|
104
|
+
a signed claim disagrees with the outer copy.
|
|
69
105
|
|
|
70
106
|
## Frozen Fields
|
|
71
107
|
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Offline Base (EVM) payer verification for Chit402 receipts.
|
|
3
|
+
*
|
|
4
|
+
* When payment.ref starts with `base:` or `eip155:8453:`, read the USDC Transfer
|
|
5
|
+
* event and confirm the sender matches caller_binding.payer_wallet (EIP-3009
|
|
6
|
+
* transferWithAuthorization records `from` as the payer).
|
|
7
|
+
*/
|
|
8
|
+
import { type TransactionReceipt } from 'ethers';
|
|
9
|
+
/** ERC-20 Transfer(address,address,uint256) topic. */
|
|
10
|
+
export declare const ERC20_TRANSFER_TOPIC = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef";
|
|
11
|
+
/** Known USDC contract addresses by network key. */
|
|
12
|
+
export declare const USDC_ADDRESSES: Record<string, string>;
|
|
13
|
+
/** Default Base mainnet RPC. */
|
|
14
|
+
export declare const BASE_RPC_URL = "https://mainnet.base.org";
|
|
15
|
+
export interface BasePayerVerification {
|
|
16
|
+
checked: boolean;
|
|
17
|
+
valid: boolean;
|
|
18
|
+
txHash?: string;
|
|
19
|
+
payerWallet?: string;
|
|
20
|
+
payee?: string;
|
|
21
|
+
asset?: string;
|
|
22
|
+
expectedAmount?: string;
|
|
23
|
+
transferredAmount?: string;
|
|
24
|
+
network?: string;
|
|
25
|
+
reason?: string;
|
|
26
|
+
}
|
|
27
|
+
export type BaseReceiptFetcher = (txHash: string, rpcUrl: string) => Promise<TransactionReceipt | null>;
|
|
28
|
+
/**
|
|
29
|
+
* True for a valid EVM address (0x + 40 hex).
|
|
30
|
+
*/
|
|
31
|
+
export declare function isEvmAddress(value: unknown): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Parse Base payment.ref into { network, txHash }.
|
|
34
|
+
* Supports `base:0x…`, `base-sepolia:0x…`, `eip155:8453:0x…`.
|
|
35
|
+
*/
|
|
36
|
+
export declare function parseBasePaymentRef(paymentRef: string | null | undefined): {
|
|
37
|
+
network: string;
|
|
38
|
+
txHash: string;
|
|
39
|
+
} | null;
|
|
40
|
+
/**
|
|
41
|
+
* Sum USDC Transfer amounts from payer in a transaction receipt.
|
|
42
|
+
* When `payee` is set, only transfers to that address are counted.
|
|
43
|
+
*/
|
|
44
|
+
export declare function sumUsdcTransfersFromPayer(receipt: TransactionReceipt, payerWallet: string, usdcAddress: string, payee?: string): bigint;
|
|
45
|
+
/**
|
|
46
|
+
* Default ethers provider fetcher for getTransactionReceipt.
|
|
47
|
+
*/
|
|
48
|
+
export declare function fetchBaseTransactionReceipt(txHash: string, rpcUrl?: string): Promise<TransactionReceipt | null>;
|
|
49
|
+
export interface VerifyBasePayerInput {
|
|
50
|
+
paymentRef: string;
|
|
51
|
+
payerWallet: string;
|
|
52
|
+
grossAmount: string | number | bigint;
|
|
53
|
+
/** Settlement payee. When set, the USDC Transfer `to` must equal this address. */
|
|
54
|
+
payee?: string;
|
|
55
|
+
/** Token contract. When set, it must be the network USDC and the Transfer log address. */
|
|
56
|
+
asset?: string;
|
|
57
|
+
network?: string;
|
|
58
|
+
rpcUrl?: string;
|
|
59
|
+
fetchReceipt?: BaseReceiptFetcher;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Verify caller_binding.payer_wallet against a Base USDC settlement tx.
|
|
63
|
+
*/
|
|
64
|
+
export declare function verifyBasePayer(input: VerifyBasePayerInput): Promise<BasePayerVerification>;
|
|
65
|
+
//# sourceMappingURL=base-payer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-payer.d.ts","sourceRoot":"","sources":["../src/base-payer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAA+B,KAAK,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAE9E,sDAAsD;AACtD,eAAO,MAAM,oBAAoB,uEAAuE,CAAC;AAEzG,oDAAoD;AACpD,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAKjD,CAAC;AAEF,gCAAgC;AAChC,eAAO,MAAM,YAAY,6BAA6B,CAAC;AAEvD,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,kBAAkB,GAAG,CAC/B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,KACX,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC;AAMxC;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEpD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACpC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CA2B5C;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,kBAAkB,EAC3B,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,KAAK,CAAC,EAAE,MAAM,GACb,MAAM,CAqBR;AAED;;GAEG;AACH,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAMpC;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IACtC,kFAAkF;IAClF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0FAA0F;IAC1F,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,kBAAkB,CAAC;CACnC;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAwHjG"}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Offline Base (EVM) payer verification for Chit402 receipts.
|
|
4
|
+
*
|
|
5
|
+
* When payment.ref starts with `base:` or `eip155:8453:`, read the USDC Transfer
|
|
6
|
+
* event and confirm the sender matches caller_binding.payer_wallet (EIP-3009
|
|
7
|
+
* transferWithAuthorization records `from` as the payer).
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.BASE_RPC_URL = exports.USDC_ADDRESSES = exports.ERC20_TRANSFER_TOPIC = void 0;
|
|
11
|
+
exports.isEvmAddress = isEvmAddress;
|
|
12
|
+
exports.parseBasePaymentRef = parseBasePaymentRef;
|
|
13
|
+
exports.sumUsdcTransfersFromPayer = sumUsdcTransfersFromPayer;
|
|
14
|
+
exports.fetchBaseTransactionReceipt = fetchBaseTransactionReceipt;
|
|
15
|
+
exports.verifyBasePayer = verifyBasePayer;
|
|
16
|
+
const ethers_1 = require("ethers");
|
|
17
|
+
/** ERC-20 Transfer(address,address,uint256) topic. */
|
|
18
|
+
exports.ERC20_TRANSFER_TOPIC = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef';
|
|
19
|
+
/** Known USDC contract addresses by network key. */
|
|
20
|
+
exports.USDC_ADDRESSES = {
|
|
21
|
+
base: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
|
|
22
|
+
'base-sepolia': '0x036CbD53842c5426634e7929541eC2318f3dCF7e',
|
|
23
|
+
'eip155:8453': '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
|
|
24
|
+
'eip155:84532': '0x036CbD53842c5426634e7929541eC2318f3dCF7e',
|
|
25
|
+
};
|
|
26
|
+
/** Default Base mainnet RPC. */
|
|
27
|
+
exports.BASE_RPC_URL = 'https://mainnet.base.org';
|
|
28
|
+
function resolveRpcUrl(override) {
|
|
29
|
+
return override || process.env.BASE_RPC_URL || exports.BASE_RPC_URL;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* True for a valid EVM address (0x + 40 hex).
|
|
33
|
+
*/
|
|
34
|
+
function isEvmAddress(value) {
|
|
35
|
+
return typeof value === 'string' && /^0x[0-9a-fA-F]{40}$/.test(value);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Parse Base payment.ref into { network, txHash }.
|
|
39
|
+
* Supports `base:0x…`, `base-sepolia:0x…`, `eip155:8453:0x…`.
|
|
40
|
+
*/
|
|
41
|
+
function parseBasePaymentRef(paymentRef) {
|
|
42
|
+
if (!paymentRef || typeof paymentRef !== 'string')
|
|
43
|
+
return null;
|
|
44
|
+
const trimmed = paymentRef.trim();
|
|
45
|
+
const lower = trimmed.toLowerCase();
|
|
46
|
+
if (lower.startsWith('eip155:')) {
|
|
47
|
+
const parts = trimmed.split(':');
|
|
48
|
+
if (parts.length < 3)
|
|
49
|
+
return null;
|
|
50
|
+
const txHash = parts.slice(2).join(':');
|
|
51
|
+
if (!/^0x[0-9a-fA-F]{64}$/.test(txHash))
|
|
52
|
+
return null;
|
|
53
|
+
const network = `${parts[0]}:${parts[1]}`.toLowerCase();
|
|
54
|
+
return { network, txHash };
|
|
55
|
+
}
|
|
56
|
+
if (lower.startsWith('base-sepolia:')) {
|
|
57
|
+
const txHash = trimmed.slice('base-sepolia:'.length);
|
|
58
|
+
if (!/^0x[0-9a-fA-F]{64}$/.test(txHash))
|
|
59
|
+
return null;
|
|
60
|
+
return { network: 'base-sepolia', txHash };
|
|
61
|
+
}
|
|
62
|
+
if (lower.startsWith('base:')) {
|
|
63
|
+
const txHash = trimmed.slice('base:'.length);
|
|
64
|
+
if (!/^0x[0-9a-fA-F]{64}$/.test(txHash))
|
|
65
|
+
return null;
|
|
66
|
+
return { network: 'base', txHash };
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Sum USDC Transfer amounts from payer in a transaction receipt.
|
|
72
|
+
* When `payee` is set, only transfers to that address are counted.
|
|
73
|
+
*/
|
|
74
|
+
function sumUsdcTransfersFromPayer(receipt, payerWallet, usdcAddress, payee) {
|
|
75
|
+
const expectedFrom = (0, ethers_1.getAddress)(payerWallet).toLowerCase();
|
|
76
|
+
const expectedTo = payee ? (0, ethers_1.getAddress)(payee).toLowerCase() : null;
|
|
77
|
+
const usdcLower = usdcAddress.toLowerCase();
|
|
78
|
+
let total = 0n;
|
|
79
|
+
for (const log of receipt.logs || []) {
|
|
80
|
+
if (log.address?.toLowerCase() !== usdcLower)
|
|
81
|
+
continue;
|
|
82
|
+
if (log.topics?.[0]?.toLowerCase() !== exports.ERC20_TRANSFER_TOPIC)
|
|
83
|
+
continue;
|
|
84
|
+
if ((log.topics?.length || 0) < 3)
|
|
85
|
+
continue;
|
|
86
|
+
const from = ('0x' + log.topics[1].slice(26)).toLowerCase();
|
|
87
|
+
if (from !== expectedFrom)
|
|
88
|
+
continue;
|
|
89
|
+
if (expectedTo) {
|
|
90
|
+
const to = ('0x' + log.topics[2].slice(26)).toLowerCase();
|
|
91
|
+
if (to !== expectedTo)
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
total += BigInt(log.data || '0');
|
|
95
|
+
}
|
|
96
|
+
return total;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Default ethers provider fetcher for getTransactionReceipt.
|
|
100
|
+
*/
|
|
101
|
+
async function fetchBaseTransactionReceipt(txHash, rpcUrl) {
|
|
102
|
+
const provider = new ethers_1.JsonRpcProvider(resolveRpcUrl(rpcUrl), undefined, {
|
|
103
|
+
staticNetwork: true,
|
|
104
|
+
batchMaxCount: 1,
|
|
105
|
+
});
|
|
106
|
+
return provider.getTransactionReceipt(txHash);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Verify caller_binding.payer_wallet against a Base USDC settlement tx.
|
|
110
|
+
*/
|
|
111
|
+
async function verifyBasePayer(input) {
|
|
112
|
+
const parsed = parseBasePaymentRef(input.paymentRef);
|
|
113
|
+
if (!parsed) {
|
|
114
|
+
return { checked: false, valid: false, reason: 'not_base_payment_ref' };
|
|
115
|
+
}
|
|
116
|
+
const payerWallet = String(input.payerWallet || '').trim();
|
|
117
|
+
if (!isEvmAddress(payerWallet)) {
|
|
118
|
+
return { checked: false, valid: false, reason: 'invalid_evm_payer_wallet' };
|
|
119
|
+
}
|
|
120
|
+
const expectedAmount = BigInt(String(input.grossAmount ?? '0'));
|
|
121
|
+
if (expectedAmount <= 0n) {
|
|
122
|
+
return { checked: false, valid: false, reason: 'invalid_gross_amount' };
|
|
123
|
+
}
|
|
124
|
+
let payee;
|
|
125
|
+
if (input.payee != null && input.payee !== '') {
|
|
126
|
+
if (!isEvmAddress(input.payee)) {
|
|
127
|
+
return { checked: false, valid: false, reason: 'invalid_payee' };
|
|
128
|
+
}
|
|
129
|
+
payee = (0, ethers_1.getAddress)(input.payee);
|
|
130
|
+
}
|
|
131
|
+
const network = (input.network || parsed.network).toLowerCase();
|
|
132
|
+
const usdcAddress = exports.USDC_ADDRESSES[network];
|
|
133
|
+
if (!usdcAddress) {
|
|
134
|
+
return { checked: false, valid: false, reason: `unknown_network: ${network}` };
|
|
135
|
+
}
|
|
136
|
+
let asset;
|
|
137
|
+
if (input.asset != null && input.asset !== '') {
|
|
138
|
+
if (!isEvmAddress(input.asset)) {
|
|
139
|
+
return { checked: true, valid: false, reason: `asset_mismatch: ${input.asset} is not an EVM token address` };
|
|
140
|
+
}
|
|
141
|
+
asset = (0, ethers_1.getAddress)(input.asset);
|
|
142
|
+
if (asset !== (0, ethers_1.getAddress)(usdcAddress)) {
|
|
143
|
+
return {
|
|
144
|
+
checked: true,
|
|
145
|
+
valid: false,
|
|
146
|
+
payerWallet: (0, ethers_1.getAddress)(payerWallet),
|
|
147
|
+
payee,
|
|
148
|
+
asset,
|
|
149
|
+
expectedAmount: expectedAmount.toString(),
|
|
150
|
+
network,
|
|
151
|
+
reason: `asset_mismatch: ${asset} !== ${(0, ethers_1.getAddress)(usdcAddress)}`,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
const fetcher = input.fetchReceipt || fetchBaseTransactionReceipt;
|
|
156
|
+
const rpcUrl = resolveRpcUrl(input.rpcUrl);
|
|
157
|
+
let receipt;
|
|
158
|
+
try {
|
|
159
|
+
receipt = await fetcher(parsed.txHash, rpcUrl);
|
|
160
|
+
}
|
|
161
|
+
catch (err) {
|
|
162
|
+
return {
|
|
163
|
+
checked: true,
|
|
164
|
+
valid: false,
|
|
165
|
+
txHash: parsed.txHash,
|
|
166
|
+
payerWallet: (0, ethers_1.getAddress)(payerWallet),
|
|
167
|
+
expectedAmount: expectedAmount.toString(),
|
|
168
|
+
network,
|
|
169
|
+
reason: `rpc_error: ${err.message}`,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
const baseFields = {
|
|
173
|
+
txHash: parsed.txHash,
|
|
174
|
+
payerWallet: (0, ethers_1.getAddress)(payerWallet),
|
|
175
|
+
payee,
|
|
176
|
+
asset: asset || (0, ethers_1.getAddress)(usdcAddress),
|
|
177
|
+
expectedAmount: expectedAmount.toString(),
|
|
178
|
+
network,
|
|
179
|
+
};
|
|
180
|
+
if (!receipt) {
|
|
181
|
+
return {
|
|
182
|
+
checked: true,
|
|
183
|
+
valid: false,
|
|
184
|
+
...baseFields,
|
|
185
|
+
reason: 'transaction_not_found',
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
if (receipt.status === 0) {
|
|
189
|
+
return {
|
|
190
|
+
checked: true,
|
|
191
|
+
valid: false,
|
|
192
|
+
...baseFields,
|
|
193
|
+
reason: 'transaction_reverted',
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
const token = asset || usdcAddress;
|
|
197
|
+
const transferred = sumUsdcTransfersFromPayer(receipt, payerWallet, token, payee);
|
|
198
|
+
const fromPayer = payee
|
|
199
|
+
? sumUsdcTransfersFromPayer(receipt, payerWallet, token)
|
|
200
|
+
: transferred;
|
|
201
|
+
const valid = transferred >= expectedAmount;
|
|
202
|
+
let reason;
|
|
203
|
+
if (!valid) {
|
|
204
|
+
if (payee && fromPayer > 0n && transferred === 0n) {
|
|
205
|
+
reason = `payee_mismatch: no USDC transfer from ${(0, ethers_1.getAddress)(payerWallet)} to ${payee}`;
|
|
206
|
+
}
|
|
207
|
+
else if (transferred > 0n) {
|
|
208
|
+
reason = `transferred_${transferred}_lt_expected_${expectedAmount}`;
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
reason = `no_usdc_transfer_from_${(0, ethers_1.getAddress)(payerWallet)}`;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return {
|
|
215
|
+
checked: true,
|
|
216
|
+
valid,
|
|
217
|
+
...baseFields,
|
|
218
|
+
transferredAmount: transferred.toString(),
|
|
219
|
+
reason,
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
//# sourceMappingURL=base-payer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-payer.js","sourceRoot":"","sources":["../src/base-payer.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -24,15 +24,25 @@ xfuel-verify — Offline verification for Chit402 receipts
|
|
|
24
24
|
Usage:
|
|
25
25
|
xfuel-verify <receipt.json> Verify binding locally
|
|
26
26
|
xfuel-verify <receipt.json> --jwks-file <jwks.json>
|
|
27
|
-
Verify issuer signature with JWKS
|
|
28
|
-
xfuel-verify <receipt.json> --
|
|
29
|
-
|
|
27
|
+
Verify issuer signature with a JWKS file
|
|
28
|
+
xfuel-verify <receipt.json> --fetch-jwks
|
|
29
|
+
Fetch JWKS from an allowlisted issuer jwks_uri
|
|
30
|
+
xfuel-verify <receipt.json> --check-payer
|
|
31
|
+
Confirm payer, payee, asset, and amount on-chain
|
|
30
32
|
xfuel-verify - < receipt.json Read from stdin
|
|
31
33
|
xfuel-verify --help Show this help
|
|
32
34
|
|
|
33
35
|
Options:
|
|
34
|
-
--jwks-file <path> JWKS file
|
|
36
|
+
--jwks-file <path> JWKS file. Keys are trusted and matched by kid (no network)
|
|
37
|
+
--jwks-url <url> Fetch this https JWKS and trust it (explicit; any host)
|
|
38
|
+
--fetch-jwks Fetch receipt verification.jwks_uri when the host is allowlisted
|
|
39
|
+
(default allowlist: api.chit402.com)
|
|
40
|
+
--trusted-kid <kid> Replace the default offline pin with this RFC 7638 kid
|
|
41
|
+
(repeatable). Default pin: ${index_js_1.DEFAULT_TRUSTED_ISSUER_KIDS[0]}
|
|
42
|
+
--no-trusted-kid Do not use the default offline pin (JWKS only)
|
|
35
43
|
--check-nullifier Query Base RPC for nullifier anchor (requires network)
|
|
44
|
+
--check-payer Query Base or Solana RPC. Base confirms payer, payee, asset, amount
|
|
45
|
+
--solana-rpc <url> Solana RPC URL (default: https://api.mainnet-beta.solana.com or SOLANA_RPC_URL)
|
|
36
46
|
--rpc <url> Custom RPC URL (default: https://mainnet.base.org)
|
|
37
47
|
--json Output JSON instead of human-readable
|
|
38
48
|
--quiet Only output errors
|
|
@@ -40,15 +50,25 @@ Options:
|
|
|
40
50
|
Exit codes:
|
|
41
51
|
0 = verified
|
|
42
52
|
1 = verification failed
|
|
43
|
-
2 = partial verification
|
|
53
|
+
2 = partial verification
|
|
44
54
|
3 = input error
|
|
45
55
|
|
|
56
|
+
Trust:
|
|
57
|
+
A signature counts only when the verifying key is trusted. Trust is a JWKS
|
|
58
|
+
entry matched by kid (file, --jwks-url, or --fetch-jwks), or an embedded
|
|
59
|
+
issuer_jwk whose RFC 7638 thumbprint equals a pinned trusted kid. The
|
|
60
|
+
embedded key alone is not a trust root. Untrusted keys report "key untrusted".
|
|
61
|
+
|
|
62
|
+
Amount, payer, payee, and tx are read from verified signed claims. A mismatch
|
|
63
|
+
with the unsigned outer payment / caller_binding copy is a failure.
|
|
64
|
+
|
|
46
65
|
Network behavior:
|
|
47
66
|
By default, no network requests are made. Network is only used when:
|
|
67
|
+
- --fetch-jwks or --jwks-url is passed
|
|
48
68
|
- --check-nullifier is passed (queries Base RPC for on-chain anchor)
|
|
69
|
+
- --check-payer is passed (queries Base or Solana RPC for USDC settlement)
|
|
49
70
|
|
|
50
|
-
|
|
51
|
-
automatically fetch JWKS from a URL to ensure offline verification.
|
|
71
|
+
Solana payer verify uses SOLANA_RPC_URL when set, else the public mainnet RPC.
|
|
52
72
|
|
|
53
73
|
Examples:
|
|
54
74
|
# Local binding verification (no network)
|
|
@@ -67,8 +87,14 @@ function parseArgs(args) {
|
|
|
67
87
|
const result = {
|
|
68
88
|
file: null,
|
|
69
89
|
jwksFile: null,
|
|
90
|
+
jwksUrl: null,
|
|
91
|
+
fetchJwks: false,
|
|
92
|
+
trustedKids: null,
|
|
93
|
+
noTrustedKid: false,
|
|
70
94
|
checkNullifier: false,
|
|
95
|
+
checkPayer: false,
|
|
71
96
|
rpcUrl: null,
|
|
97
|
+
solanaRpcUrl: null,
|
|
72
98
|
json: false,
|
|
73
99
|
quiet: false,
|
|
74
100
|
help: false,
|
|
@@ -81,12 +107,31 @@ function parseArgs(args) {
|
|
|
81
107
|
else if (arg === '--check-nullifier') {
|
|
82
108
|
result.checkNullifier = true;
|
|
83
109
|
}
|
|
110
|
+
else if (arg === '--check-payer') {
|
|
111
|
+
result.checkPayer = true;
|
|
112
|
+
}
|
|
84
113
|
else if (arg === '--jwks-file' && args[i + 1]) {
|
|
85
114
|
result.jwksFile = args[++i];
|
|
86
115
|
}
|
|
116
|
+
else if (arg === '--jwks-url' && args[i + 1]) {
|
|
117
|
+
result.jwksUrl = args[++i];
|
|
118
|
+
}
|
|
119
|
+
else if (arg === '--fetch-jwks') {
|
|
120
|
+
result.fetchJwks = true;
|
|
121
|
+
}
|
|
122
|
+
else if (arg === '--trusted-kid' && args[i + 1]) {
|
|
123
|
+
result.trustedKids = result.trustedKids || [];
|
|
124
|
+
result.trustedKids.push(args[++i]);
|
|
125
|
+
}
|
|
126
|
+
else if (arg === '--no-trusted-kid') {
|
|
127
|
+
result.noTrustedKid = true;
|
|
128
|
+
}
|
|
87
129
|
else if (arg === '--rpc' && args[i + 1]) {
|
|
88
130
|
result.rpcUrl = args[++i];
|
|
89
131
|
}
|
|
132
|
+
else if (arg === '--solana-rpc' && args[i + 1]) {
|
|
133
|
+
result.solanaRpcUrl = args[++i];
|
|
134
|
+
}
|
|
90
135
|
else if (arg === '--json') {
|
|
91
136
|
result.json = true;
|
|
92
137
|
}
|
|
@@ -148,10 +193,18 @@ async function main() {
|
|
|
148
193
|
return 3;
|
|
149
194
|
}
|
|
150
195
|
}
|
|
196
|
+
const trustedKids = args.noTrustedKid
|
|
197
|
+
? []
|
|
198
|
+
: (args.trustedKids ?? undefined);
|
|
151
199
|
const result = await (0, index_js_1.verifyReceipt)(receipt, {
|
|
152
200
|
jwks,
|
|
201
|
+
jwksUri: args.jwksUrl || undefined,
|
|
202
|
+
fetchJwks: args.fetchJwks,
|
|
203
|
+
trustedKids,
|
|
153
204
|
checkNullifier: args.checkNullifier,
|
|
205
|
+
checkPayer: args.checkPayer,
|
|
154
206
|
rpcUrl: args.rpcUrl || undefined,
|
|
207
|
+
solanaRpcUrl: args.solanaRpcUrl || undefined,
|
|
155
208
|
});
|
|
156
209
|
if (args.json) {
|
|
157
210
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -163,7 +216,7 @@ async function main() {
|
|
|
163
216
|
console.log(` Receipt ID: ${result.receipt_id}`);
|
|
164
217
|
console.log(` Hub: ${result.hub || '—'}`);
|
|
165
218
|
console.log(` Model: ${result.model || '—'}`);
|
|
166
|
-
console.log(` Amount: ${formatAmount(result.amount_usdc)}`);
|
|
219
|
+
console.log(` Amount: ${result.issuer_signature.valid ? formatAmount(result.amount_usdc) : '— (not verified)'}`);
|
|
167
220
|
console.log(` TX: ${result.tx || '—'}`);
|
|
168
221
|
console.log(` Output Hash: ${result.output_hash ? result.output_hash.slice(0, 18) + '…' : '—'}`);
|
|
169
222
|
console.log('');
|
|
@@ -176,7 +229,7 @@ async function main() {
|
|
|
176
229
|
console.log(` Covers: ${result.binding.covers.join(', ')}`);
|
|
177
230
|
}
|
|
178
231
|
else {
|
|
179
|
-
console.log(` Status:
|
|
232
|
+
console.log(` Status: ${result.binding.reason || 'No payment-binding commitment'}`);
|
|
180
233
|
}
|
|
181
234
|
console.log('');
|
|
182
235
|
console.log(` Issuer Signature`);
|
|
@@ -184,14 +237,43 @@ async function main() {
|
|
|
184
237
|
if (result.issuer_signature.checked) {
|
|
185
238
|
console.log(` Kid: ${result.issuer_signature.kid || '—'}`);
|
|
186
239
|
console.log(` Valid: ${result.issuer_signature.valid ? '✓ YES' : '✗ NO'}`);
|
|
240
|
+
console.log(` Key trusted: ${result.issuer_signature.key_trusted ? '✓ YES' : '✗ NO'}${result.issuer_signature.trust ? ` (${result.issuer_signature.trust})` : ''}`);
|
|
187
241
|
if (!result.issuer_signature.valid && result.issuer_signature.reason) {
|
|
188
242
|
console.log(` Reason: ${result.issuer_signature.reason}`);
|
|
189
243
|
}
|
|
190
244
|
}
|
|
191
245
|
else {
|
|
192
246
|
console.log(` Status: ${result.issuer_signature.reason || 'Not checked'}`);
|
|
193
|
-
if (receipt.issuer_signature && !args.jwksFile) {
|
|
194
|
-
console.log(` (
|
|
247
|
+
if (receipt.issuer_signature && !args.jwksFile && !args.fetchJwks && !args.jwksUrl) {
|
|
248
|
+
console.log(` (pass --jwks-file, --fetch-jwks, or rely on the default trusted kid)`);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
console.log('');
|
|
252
|
+
console.log(` Payer (on-chain)`);
|
|
253
|
+
console.log(` ─────────────────────────────────────────────────`);
|
|
254
|
+
if (result.payer.checked) {
|
|
255
|
+
console.log(` Rail: ${result.payer.rail || '—'}`);
|
|
256
|
+
console.log(` Payer: ${result.payer.payer_wallet || '—'}`);
|
|
257
|
+
console.log(` Payee: ${result.payer.payee || '—'}`);
|
|
258
|
+
console.log(` Asset: ${result.payer.asset || '—'}`);
|
|
259
|
+
console.log(` Amount: ${formatAmount(result.payer.amount || null)}`);
|
|
260
|
+
console.log(` Valid: ${result.payer.valid ? '✓ YES' : '✗ NO'}`);
|
|
261
|
+
if (!result.payer.valid && result.payer.reason) {
|
|
262
|
+
console.log(` Reason: ${result.payer.reason}`);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
console.log(` Status: ${result.payer.reason || 'Not checked'}`);
|
|
267
|
+
if (result.issuer_signature.valid && result.payer.payer_wallet && result.tx && !args.checkPayer) {
|
|
268
|
+
console.log(` (pass --check-payer to verify payer, payee, asset, and amount on-chain)`);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
if (result.claim_mismatches.length > 0) {
|
|
272
|
+
console.log('');
|
|
273
|
+
console.log(` Outer / signed mismatches`);
|
|
274
|
+
console.log(` ─────────────────────────────────────────────────`);
|
|
275
|
+
for (const mismatch of result.claim_mismatches) {
|
|
276
|
+
console.log(` ${mismatch.field}: outer ${mismatch.outer} ≠ signed ${mismatch.signed}`);
|
|
195
277
|
}
|
|
196
278
|
}
|
|
197
279
|
console.log('');
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;AACA;;;;;;;;;;;;;;GAcG;;AAEH,qCAAuC;AACvC,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|