@xfuel/verify 0.1.0 → 0.1.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 +22 -4
- package/dist/base-payer.d.ts +58 -0
- package/dist/base-payer.d.ts.map +1 -0
- package/dist/base-payer.js +178 -0
- package/dist/base-payer.js.map +1 -0
- package/dist/cli.js +38 -3
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +47 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +141 -15
- package/dist/index.js.map +1 -1
- package/dist/jws.d.ts +23 -0
- package/dist/jws.d.ts.map +1 -0
- package/dist/jws.js +59 -0
- package/dist/jws.js.map +1 -0
- package/dist/payer.d.ts +54 -0
- package/dist/payer.d.ts.map +1 -0
- package/dist/payer.js +136 -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 +1 -1
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Offline Solana payer verification for Chit402 receipts.
|
|
3
|
+
*
|
|
4
|
+
* When payment.ref starts with `solana:`, fetch the settled transaction and
|
|
5
|
+
* confirm a USDC transfer of payment.gross_amount involving caller_binding.payer_wallet
|
|
6
|
+
* as authority (x402 exact-svm) without trusting Chit logs.
|
|
7
|
+
*/
|
|
8
|
+
/** Solana mainnet USDC mint (SPL, 6 decimals). */
|
|
9
|
+
export declare const SOLANA_USDC_MINT_MAINNET = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
|
|
10
|
+
/** Solana devnet USDC mint (SPL, 6 decimals). */
|
|
11
|
+
export declare const SOLANA_USDC_MINT_DEVNET = "Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr";
|
|
12
|
+
/** Default public Solana mainnet RPC (override with SOLANA_RPC_URL). */
|
|
13
|
+
export declare const SOLANA_RPC_URL = "https://api.mainnet-beta.solana.com";
|
|
14
|
+
export interface SolanaPayerVerification {
|
|
15
|
+
checked: boolean;
|
|
16
|
+
valid: boolean;
|
|
17
|
+
signature?: string;
|
|
18
|
+
payerWallet?: string;
|
|
19
|
+
expectedAmount?: string;
|
|
20
|
+
transferredAmount?: string;
|
|
21
|
+
mint?: string;
|
|
22
|
+
reason?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface SolanaRpcGetTransactionResult {
|
|
25
|
+
meta?: {
|
|
26
|
+
err?: unknown;
|
|
27
|
+
preTokenBalances?: Array<{
|
|
28
|
+
accountIndex: number;
|
|
29
|
+
mint: string;
|
|
30
|
+
owner?: string;
|
|
31
|
+
uiTokenAmount?: {
|
|
32
|
+
amount: string;
|
|
33
|
+
};
|
|
34
|
+
}>;
|
|
35
|
+
postTokenBalances?: Array<{
|
|
36
|
+
accountIndex: number;
|
|
37
|
+
mint: string;
|
|
38
|
+
owner?: string;
|
|
39
|
+
uiTokenAmount?: {
|
|
40
|
+
amount: string;
|
|
41
|
+
};
|
|
42
|
+
}>;
|
|
43
|
+
} | null;
|
|
44
|
+
transaction?: {
|
|
45
|
+
message?: {
|
|
46
|
+
accountKeys?: Array<{
|
|
47
|
+
pubkey: string;
|
|
48
|
+
signer?: boolean;
|
|
49
|
+
} | string>;
|
|
50
|
+
instructions?: Array<{
|
|
51
|
+
program?: string;
|
|
52
|
+
programId?: string;
|
|
53
|
+
parsed?: {
|
|
54
|
+
type?: string;
|
|
55
|
+
info?: Record<string, unknown>;
|
|
56
|
+
};
|
|
57
|
+
}>;
|
|
58
|
+
};
|
|
59
|
+
signatures?: string[];
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
export type SolanaRpcFetcher = (signature: string, rpcUrl: string) => Promise<SolanaRpcGetTransactionResult | null>;
|
|
63
|
+
/**
|
|
64
|
+
* True for a plausible Solana base58 pubkey (32–44 chars).
|
|
65
|
+
*/
|
|
66
|
+
export declare function isSolanaBase58Pubkey(value: unknown): boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Extract the tx signature from `solana:<sig>` payment.ref.
|
|
69
|
+
*/
|
|
70
|
+
export declare function parseSolanaPaymentRef(paymentRef: string | null | undefined): string | null;
|
|
71
|
+
/**
|
|
72
|
+
* Parse USDC transfer instructions from a jsonParsed getTransaction result.
|
|
73
|
+
*/
|
|
74
|
+
export declare function extractUsdcTransfersFromTx(tx: SolanaRpcGetTransactionResult, mint?: string): Array<{
|
|
75
|
+
authority: string;
|
|
76
|
+
amount: bigint;
|
|
77
|
+
mint: string;
|
|
78
|
+
}>;
|
|
79
|
+
/**
|
|
80
|
+
* Fallback: infer USDC outflow from pre/post token balance deltas for a payer owner.
|
|
81
|
+
*/
|
|
82
|
+
export declare function inferUsdcOutflowFromBalances(tx: SolanaRpcGetTransactionResult, payerWallet: string, mint?: string): bigint;
|
|
83
|
+
/**
|
|
84
|
+
* Default JSON-RPC fetcher for getTransaction (jsonParsed).
|
|
85
|
+
*/
|
|
86
|
+
export declare function fetchSolanaTransaction(signature: string, rpcUrl?: string): Promise<SolanaRpcGetTransactionResult | null>;
|
|
87
|
+
export interface VerifySolanaPayerInput {
|
|
88
|
+
paymentRef: string;
|
|
89
|
+
payerWallet: string;
|
|
90
|
+
grossAmount: string | number | bigint;
|
|
91
|
+
mint?: string;
|
|
92
|
+
rpcUrl?: string;
|
|
93
|
+
fetchTransaction?: SolanaRpcFetcher;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Verify caller_binding.payer_wallet against a Solana USDC settlement tx.
|
|
97
|
+
*/
|
|
98
|
+
export declare function verifySolanaPayer(input: VerifySolanaPayerInput): Promise<SolanaPayerVerification>;
|
|
99
|
+
//# sourceMappingURL=solana-payer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"solana-payer.d.ts","sourceRoot":"","sources":["../src/solana-payer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Offline Solana payer verification for Chit402 receipts.
|
|
4
|
+
*
|
|
5
|
+
* When payment.ref starts with `solana:`, fetch the settled transaction and
|
|
6
|
+
* confirm a USDC transfer of payment.gross_amount involving caller_binding.payer_wallet
|
|
7
|
+
* as authority (x402 exact-svm) without trusting Chit logs.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.SOLANA_RPC_URL = exports.SOLANA_USDC_MINT_DEVNET = exports.SOLANA_USDC_MINT_MAINNET = void 0;
|
|
11
|
+
exports.isSolanaBase58Pubkey = isSolanaBase58Pubkey;
|
|
12
|
+
exports.parseSolanaPaymentRef = parseSolanaPaymentRef;
|
|
13
|
+
exports.extractUsdcTransfersFromTx = extractUsdcTransfersFromTx;
|
|
14
|
+
exports.inferUsdcOutflowFromBalances = inferUsdcOutflowFromBalances;
|
|
15
|
+
exports.fetchSolanaTransaction = fetchSolanaTransaction;
|
|
16
|
+
exports.verifySolanaPayer = verifySolanaPayer;
|
|
17
|
+
/** Solana mainnet USDC mint (SPL, 6 decimals). */
|
|
18
|
+
exports.SOLANA_USDC_MINT_MAINNET = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';
|
|
19
|
+
/** Solana devnet USDC mint (SPL, 6 decimals). */
|
|
20
|
+
exports.SOLANA_USDC_MINT_DEVNET = 'Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr';
|
|
21
|
+
/** Default public Solana mainnet RPC (override with SOLANA_RPC_URL). */
|
|
22
|
+
exports.SOLANA_RPC_URL = 'https://api.mainnet-beta.solana.com';
|
|
23
|
+
/** SPL Token program id. */
|
|
24
|
+
const TOKEN_PROGRAM_ID = 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA';
|
|
25
|
+
/** Base58 alphabet (no 0, O, I, l). */
|
|
26
|
+
const BASE58_RE = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
|
|
27
|
+
function resolveRpcUrl(override) {
|
|
28
|
+
return override || process.env.SOLANA_RPC_URL || exports.SOLANA_RPC_URL;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* True for a plausible Solana base58 pubkey (32–44 chars).
|
|
32
|
+
*/
|
|
33
|
+
function isSolanaBase58Pubkey(value) {
|
|
34
|
+
return typeof value === 'string' && BASE58_RE.test(value);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Extract the tx signature from `solana:<sig>` payment.ref.
|
|
38
|
+
*/
|
|
39
|
+
function parseSolanaPaymentRef(paymentRef) {
|
|
40
|
+
if (!paymentRef || typeof paymentRef !== 'string')
|
|
41
|
+
return null;
|
|
42
|
+
const trimmed = paymentRef.trim();
|
|
43
|
+
if (!trimmed.toLowerCase().startsWith('solana:'))
|
|
44
|
+
return null;
|
|
45
|
+
const sig = trimmed.slice('solana:'.length).trim();
|
|
46
|
+
return sig.length > 0 ? sig : null;
|
|
47
|
+
}
|
|
48
|
+
function accountPubkey(key) {
|
|
49
|
+
return typeof key === 'string' ? key : key.pubkey;
|
|
50
|
+
}
|
|
51
|
+
function isSigner(key) {
|
|
52
|
+
return typeof key !== 'string' && key.signer === true;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Parse USDC transfer instructions from a jsonParsed getTransaction result.
|
|
56
|
+
*/
|
|
57
|
+
function extractUsdcTransfersFromTx(tx, mint = exports.SOLANA_USDC_MINT_MAINNET) {
|
|
58
|
+
const transfers = [];
|
|
59
|
+
const instructions = tx.transaction?.message?.instructions || [];
|
|
60
|
+
for (const ix of instructions) {
|
|
61
|
+
const program = ix.program || '';
|
|
62
|
+
const programId = ix.programId || '';
|
|
63
|
+
if (program !== 'spl-token' && programId !== TOKEN_PROGRAM_ID)
|
|
64
|
+
continue;
|
|
65
|
+
const parsed = ix.parsed;
|
|
66
|
+
if (!parsed || typeof parsed !== 'object')
|
|
67
|
+
continue;
|
|
68
|
+
const type = parsed.type;
|
|
69
|
+
const info = parsed.info || {};
|
|
70
|
+
if (type === 'transferChecked') {
|
|
71
|
+
const ixMint = String(info.mint || '');
|
|
72
|
+
if (ixMint !== mint)
|
|
73
|
+
continue;
|
|
74
|
+
const authority = String(info.authority || info.sourceOwner || '');
|
|
75
|
+
const tokenAmount = info.tokenAmount;
|
|
76
|
+
const raw = tokenAmount?.amount ?? info.amount;
|
|
77
|
+
if (!authority || raw == null)
|
|
78
|
+
continue;
|
|
79
|
+
transfers.push({ authority, amount: BigInt(String(raw)), mint: ixMint });
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (type === 'transfer') {
|
|
83
|
+
// Legacy transfer ix — confirm mint via token balance owner match when possible.
|
|
84
|
+
const authority = String(info.authority || info.source || '');
|
|
85
|
+
const raw = info.tokenAmount?.amount ?? info.amount;
|
|
86
|
+
if (!authority || raw == null)
|
|
87
|
+
continue;
|
|
88
|
+
transfers.push({ authority, amount: BigInt(String(raw)), mint });
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return transfers;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Fallback: infer USDC outflow from pre/post token balance deltas for a payer owner.
|
|
95
|
+
*/
|
|
96
|
+
function inferUsdcOutflowFromBalances(tx, payerWallet, mint = exports.SOLANA_USDC_MINT_MAINNET) {
|
|
97
|
+
const pre = tx.meta?.preTokenBalances || [];
|
|
98
|
+
const post = tx.meta?.postTokenBalances || [];
|
|
99
|
+
const byIndex = new Map();
|
|
100
|
+
for (const row of pre) {
|
|
101
|
+
if (row.mint !== mint || !row.owner)
|
|
102
|
+
continue;
|
|
103
|
+
const entry = byIndex.get(row.accountIndex) || {
|
|
104
|
+
pre: 0n,
|
|
105
|
+
post: 0n,
|
|
106
|
+
owner: row.owner,
|
|
107
|
+
mint: row.mint,
|
|
108
|
+
};
|
|
109
|
+
entry.pre = BigInt(row.uiTokenAmount?.amount || '0');
|
|
110
|
+
byIndex.set(row.accountIndex, entry);
|
|
111
|
+
}
|
|
112
|
+
for (const row of post) {
|
|
113
|
+
if (row.mint !== mint || !row.owner)
|
|
114
|
+
continue;
|
|
115
|
+
const entry = byIndex.get(row.accountIndex) || {
|
|
116
|
+
pre: 0n,
|
|
117
|
+
post: 0n,
|
|
118
|
+
owner: row.owner,
|
|
119
|
+
mint: row.mint,
|
|
120
|
+
};
|
|
121
|
+
entry.post = BigInt(row.uiTokenAmount?.amount || '0');
|
|
122
|
+
byIndex.set(row.accountIndex, entry);
|
|
123
|
+
}
|
|
124
|
+
let totalOut = 0n;
|
|
125
|
+
for (const entry of byIndex.values()) {
|
|
126
|
+
if (entry.owner !== payerWallet)
|
|
127
|
+
continue;
|
|
128
|
+
if (entry.pre > entry.post) {
|
|
129
|
+
totalOut += entry.pre - entry.post;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return totalOut;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Default JSON-RPC fetcher for getTransaction (jsonParsed).
|
|
136
|
+
*/
|
|
137
|
+
async function fetchSolanaTransaction(signature, rpcUrl) {
|
|
138
|
+
const url = resolveRpcUrl(rpcUrl);
|
|
139
|
+
const body = {
|
|
140
|
+
jsonrpc: '2.0',
|
|
141
|
+
id: 1,
|
|
142
|
+
method: 'getTransaction',
|
|
143
|
+
params: [signature, { encoding: 'jsonParsed', maxSupportedTransactionVersion: 0 }],
|
|
144
|
+
};
|
|
145
|
+
const res = await fetch(url, {
|
|
146
|
+
method: 'POST',
|
|
147
|
+
headers: { 'content-type': 'application/json' },
|
|
148
|
+
body: JSON.stringify(body),
|
|
149
|
+
});
|
|
150
|
+
if (!res.ok) {
|
|
151
|
+
throw new Error(`Solana RPC HTTP ${res.status}`);
|
|
152
|
+
}
|
|
153
|
+
const json = await res.json();
|
|
154
|
+
if (json.error) {
|
|
155
|
+
throw new Error(`Solana RPC error: ${json.error.message || 'unknown'}`);
|
|
156
|
+
}
|
|
157
|
+
return json.result ?? null;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Verify caller_binding.payer_wallet against a Solana USDC settlement tx.
|
|
161
|
+
*/
|
|
162
|
+
async function verifySolanaPayer(input) {
|
|
163
|
+
const signature = parseSolanaPaymentRef(input.paymentRef);
|
|
164
|
+
if (!signature) {
|
|
165
|
+
return { checked: false, valid: false, reason: 'not_solana_payment_ref' };
|
|
166
|
+
}
|
|
167
|
+
const payerWallet = String(input.payerWallet || '').trim();
|
|
168
|
+
if (!isSolanaBase58Pubkey(payerWallet)) {
|
|
169
|
+
return { checked: false, valid: false, reason: 'invalid_solana_payer_wallet' };
|
|
170
|
+
}
|
|
171
|
+
const expectedAmount = BigInt(String(input.grossAmount ?? '0'));
|
|
172
|
+
if (expectedAmount <= 0n) {
|
|
173
|
+
return { checked: false, valid: false, reason: 'invalid_gross_amount' };
|
|
174
|
+
}
|
|
175
|
+
const mint = input.mint || exports.SOLANA_USDC_MINT_MAINNET;
|
|
176
|
+
const fetcher = input.fetchTransaction || fetchSolanaTransaction;
|
|
177
|
+
const rpcUrl = resolveRpcUrl(input.rpcUrl);
|
|
178
|
+
let tx;
|
|
179
|
+
try {
|
|
180
|
+
tx = await fetcher(signature, rpcUrl);
|
|
181
|
+
}
|
|
182
|
+
catch (err) {
|
|
183
|
+
return {
|
|
184
|
+
checked: true,
|
|
185
|
+
valid: false,
|
|
186
|
+
signature,
|
|
187
|
+
payerWallet,
|
|
188
|
+
expectedAmount: expectedAmount.toString(),
|
|
189
|
+
mint,
|
|
190
|
+
reason: `rpc_error: ${err.message}`,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
if (!tx) {
|
|
194
|
+
return {
|
|
195
|
+
checked: true,
|
|
196
|
+
valid: false,
|
|
197
|
+
signature,
|
|
198
|
+
payerWallet,
|
|
199
|
+
expectedAmount: expectedAmount.toString(),
|
|
200
|
+
mint,
|
|
201
|
+
reason: 'transaction_not_found',
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
if (tx.meta?.err != null) {
|
|
205
|
+
return {
|
|
206
|
+
checked: true,
|
|
207
|
+
valid: false,
|
|
208
|
+
signature,
|
|
209
|
+
payerWallet,
|
|
210
|
+
expectedAmount: expectedAmount.toString(),
|
|
211
|
+
mint,
|
|
212
|
+
reason: 'transaction_failed',
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
const accountKeys = tx.transaction?.message?.accountKeys || [];
|
|
216
|
+
const payerIsSigner = accountKeys.some((k) => accountPubkey(k) === payerWallet && isSigner(k));
|
|
217
|
+
const transfers = extractUsdcTransfersFromTx(tx, mint);
|
|
218
|
+
const authorityMatch = transfers.find((t) => t.authority === payerWallet && t.amount >= expectedAmount);
|
|
219
|
+
if (authorityMatch) {
|
|
220
|
+
return {
|
|
221
|
+
checked: true,
|
|
222
|
+
valid: true,
|
|
223
|
+
signature,
|
|
224
|
+
payerWallet,
|
|
225
|
+
expectedAmount: expectedAmount.toString(),
|
|
226
|
+
transferredAmount: authorityMatch.amount.toString(),
|
|
227
|
+
mint,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
// x402 exact-svm: payer may co-sign while authority is their ATA owner — accept signer + balance delta.
|
|
231
|
+
const outflow = inferUsdcOutflowFromBalances(tx, payerWallet, mint);
|
|
232
|
+
if (payerIsSigner && outflow >= expectedAmount) {
|
|
233
|
+
return {
|
|
234
|
+
checked: true,
|
|
235
|
+
valid: true,
|
|
236
|
+
signature,
|
|
237
|
+
payerWallet,
|
|
238
|
+
expectedAmount: expectedAmount.toString(),
|
|
239
|
+
transferredAmount: outflow.toString(),
|
|
240
|
+
mint,
|
|
241
|
+
reason: undefined,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
const anyTransfer = transfers.find((t) => t.amount >= expectedAmount);
|
|
245
|
+
return {
|
|
246
|
+
checked: true,
|
|
247
|
+
valid: false,
|
|
248
|
+
signature,
|
|
249
|
+
payerWallet,
|
|
250
|
+
expectedAmount: expectedAmount.toString(),
|
|
251
|
+
transferredAmount: anyTransfer?.amount.toString(),
|
|
252
|
+
mint,
|
|
253
|
+
reason: anyTransfer
|
|
254
|
+
? `payer_mismatch: authority ${anyTransfer.authority} !== ${payerWallet}`
|
|
255
|
+
: `no_usdc_transfer_of_${expectedAmount.toString()}_from_${payerWallet}`,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
//# sourceMappingURL=solana-payer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"solana-payer.js","sourceRoot":"","sources":["../src/solana-payer.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED