stellar-check 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/xdr.js ADDED
@@ -0,0 +1,72 @@
1
+ import { Transaction, TransactionBuilder } from '@stellar/stellar-sdk';
2
+ import { formatAmount } from './amounts.js';
3
+ import { validateIntent } from './input.js';
4
+ /** Decode locally. This extracts a payment intent; it does not validate a transaction. */
5
+ export function importPaymentXdr(input, networkPassphrase) {
6
+ const fail = (message, unsupported = false) => ({ ok: false, code: unsupported ? 'UNSUPPORTED_XDR' : 'INVALID_XDR', message });
7
+ if (typeof networkPassphrase !== 'string' || !networkPassphrase.trim())
8
+ return fail('Choose the network explicitly. XDR does not identify its network.');
9
+ if (typeof input !== 'string' || !input.trim() || input.length > 32768)
10
+ return fail('Paste a base64 transaction envelope of at most 32 KB.');
11
+ const encoded = input.replace(/\s/g, '');
12
+ if (encoded.length % 4 !== 0 || !/^[A-Za-z0-9+/]+={0,2}$/.test(encoded))
13
+ return fail('Use the complete base64 transaction envelope, including its padding.');
14
+ try {
15
+ const tx = TransactionBuilder.fromXdr(encoded, networkPassphrase);
16
+ if (tx.toXdr() !== encoded)
17
+ return fail('The XDR is noncanonical or contains trailing data. Export a fresh transaction envelope.');
18
+ if (!(tx instanceof Transaction))
19
+ return fail('Fee-bump envelopes are outside this importer. Use one unsigned classic payment.', true);
20
+ const envelope = tx.toEnvelope();
21
+ if (envelope.type !== 'envelopeTypeTx')
22
+ return fail('Only modern V1 transaction envelopes are supported.', true);
23
+ if (tx.signatures.length)
24
+ return fail('Use an unsigned envelope. Signed transactions are outside this importer.', true);
25
+ const raw = envelope.value.tx;
26
+ if (raw.ext.type !== 'v0')
27
+ return fail('Transaction extensions, including Soroban data, are unsupported.', true);
28
+ if (raw.cond.type === 'precondV2')
29
+ return fail('Extended transaction preconditions are unsupported. They cannot be assessed by this payment checker.', true);
30
+ if (tx.operations.length !== 1)
31
+ return fail('Import exactly one classic payment operation. Batches are unsupported.', true);
32
+ const operation = tx.operations[0];
33
+ if (operation.type !== 'payment')
34
+ return fail('Only a classic payment operation is supported. Path payments and other operations are unsupported.', true);
35
+ let memo;
36
+ const decodedMemo = tx.memo;
37
+ if (decodedMemo.type !== 'none') {
38
+ const value = decodedMemo.value;
39
+ const text = value instanceof Uint8Array
40
+ ? decodedMemo.type === 'text'
41
+ ? new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(value)
42
+ : Array.from(value, byte => byte.toString(16).padStart(2, '0')).join('')
43
+ : String(value);
44
+ memo = { type: decodedMemo.type, value: text };
45
+ }
46
+ const payment = {
47
+ networkPassphrase,
48
+ source: tx.source,
49
+ destination: operation.destination,
50
+ asset: operation.asset.isNative() ? { type: 'native' } : { type: 'credit', code: operation.asset.getCode(), issuer: operation.asset.getIssuer() },
51
+ amount: operation.amount,
52
+ feeBudget: formatAmount(BigInt(tx.fee)),
53
+ ...(operation.source ? { operationSource: operation.source } : {}),
54
+ ...(memo ? { memo } : {}),
55
+ };
56
+ const validated = validateIntent(payment);
57
+ if (!('payment' in validated))
58
+ return fail(validated.issues[0].message, true);
59
+ return { ok: true, payment: validated.payment, context: {
60
+ sequence: tx.sequence,
61
+ ...(tx.timeBounds ? { timeBounds: tx.timeBounds } : {}),
62
+ limitations: [
63
+ 'The network is selected by you; it is not encoded in the envelope.',
64
+ 'Only payment readiness is assessed. Sequence numbers, time bounds, signatures and transaction execution are not validated.',
65
+ 'Editing the imported payment changes the form only. The original XDR is not modified or rebuilt.',
66
+ ],
67
+ } };
68
+ }
69
+ catch {
70
+ return fail('The envelope could not be decoded without changing its contents. Check the XDR and use a supported UTF-8 text memo.');
71
+ }
72
+ }
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "stellar-check",
3
+ "version": "0.1.0",
4
+ "description": "Read-only readiness diagnostics for classic Stellar payments",
5
+ "type": "module",
6
+ "license": "Apache-2.0",
7
+ "engines": {
8
+ "node": ">=22.12.0"
9
+ },
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "README.md",
19
+ "LICENSE"
20
+ ],
21
+ "scripts": {
22
+ "build": "tsc -p tsconfig.build.json",
23
+ "typecheck": "tsc --noEmit",
24
+ "test": "node --import tsx --test test/*.test.ts",
25
+ "check": "npm run typecheck && npm test && npm run build && npm run demo:build",
26
+ "demo": "vite demo --host 127.0.0.1",
27
+ "demo:build": "vite build demo --config demo/vite.config.ts",
28
+ "example": "node --import tsx examples/check-payment.ts",
29
+ "testnet": "node --import tsx examples/testnet.ts",
30
+ "prepack": "npm run build"
31
+ },
32
+ "dependencies": {
33
+ "@stellar/stellar-sdk": "17.0.1"
34
+ },
35
+ "devDependencies": {
36
+ "@fontsource-variable/manrope": "5.3.0",
37
+ "@fontsource/ibm-plex-mono": "5.3.0",
38
+ "@types/node": "26.4.1",
39
+ "tsx": "4.23.13",
40
+ "typescript": "7.0.2",
41
+ "vite": "8.2.2"
42
+ },
43
+ "repository": {
44
+ "type": "git",
45
+ "url": "git+https://github.com/GautamBytes/stellar-check.git"
46
+ },
47
+ "bugs": {
48
+ "url": "https://github.com/GautamBytes/stellar-check/issues"
49
+ },
50
+ "homepage": "https://stellar-check-gamma.vercel.app"
51
+ }