@leashmarket/core 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/README.md +32 -0
- package/dist/agent/agent.d.ts +8 -0
- package/dist/agent/agent.d.ts.map +1 -0
- package/dist/agent/agent.js +14 -0
- package/dist/agent/agent.js.map +1 -0
- package/dist/agent/treasury-pda.d.ts +49 -0
- package/dist/agent/treasury-pda.d.ts.map +1 -0
- package/dist/agent/treasury-pda.js +55 -0
- package/dist/agent/treasury-pda.js.map +1 -0
- package/dist/explorer/index.d.ts +55 -0
- package/dist/explorer/index.d.ts.map +1 -0
- package/dist/explorer/index.js +95 -0
- package/dist/explorer/index.js.map +1 -0
- package/dist/fees/leash-fee.d.ts +248 -0
- package/dist/fees/leash-fee.d.ts.map +1 -0
- package/dist/fees/leash-fee.js +246 -0
- package/dist/fees/leash-fee.js.map +1 -0
- package/dist/format/index.d.ts +55 -0
- package/dist/format/index.d.ts.map +1 -0
- package/dist/format/index.js +130 -0
- package/dist/format/index.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/policy/evaluate.d.ts +17 -0
- package/dist/policy/evaluate.d.ts.map +1 -0
- package/dist/policy/evaluate.js +46 -0
- package/dist/policy/evaluate.js.map +1 -0
- package/dist/policy/state.d.ts +8 -0
- package/dist/policy/state.d.ts.map +1 -0
- package/dist/policy/state.js +2 -0
- package/dist/policy/state.js.map +1 -0
- package/dist/receipt/build.d.ts +5 -0
- package/dist/receipt/build.d.ts.map +1 -0
- package/dist/receipt/build.js +9 -0
- package/dist/receipt/build.js.map +1 -0
- package/dist/receipt/hash.d.ts +15 -0
- package/dist/receipt/hash.d.ts.map +1 -0
- package/dist/receipt/hash.js +40 -0
- package/dist/receipt/hash.js.map +1 -0
- package/dist/receipt/verify.d.ts +10 -0
- package/dist/receipt/verify.d.ts.map +1 -0
- package/dist/receipt/verify.js +36 -0
- package/dist/receipt/verify.js.map +1 -0
- package/dist/tokens/index.d.ts +86 -0
- package/dist/tokens/index.d.ts.map +1 -0
- package/dist/tokens/index.js +163 -0
- package/dist/tokens/index.js.map +1 -0
- package/dist/treasury/balance.d.ts +3 -0
- package/dist/treasury/balance.d.ts.map +1 -0
- package/dist/treasury/balance.js +13 -0
- package/dist/treasury/balance.js.map +1 -0
- package/dist/treasury/inspect-token-account.d.ts +46 -0
- package/dist/treasury/inspect-token-account.d.ts.map +1 -0
- package/dist/treasury/inspect-token-account.js +67 -0
- package/dist/treasury/inspect-token-account.js.map +1 -0
- package/dist/treasury/list-balances.d.ts +57 -0
- package/dist/treasury/list-balances.d.ts.map +1 -0
- package/dist/treasury/list-balances.js +115 -0
- package/dist/treasury/list-balances.js.map +1 -0
- package/dist/treasury/pause.d.ts +32 -0
- package/dist/treasury/pause.d.ts.map +1 -0
- package/dist/treasury/pause.js +40 -0
- package/dist/treasury/pause.js.map +1 -0
- package/dist/treasury/withdraw.d.ts +13 -0
- package/dist/treasury/withdraw.d.ts.map +1 -0
- package/dist/treasury/withdraw.js +4 -0
- package/dist/treasury/withdraw.js.map +1 -0
- package/dist/wallet/index.d.ts +3 -0
- package/dist/wallet/index.d.ts.map +1 -0
- package/dist/wallet/index.js +2 -0
- package/dist/wallet/index.js.map +1 -0
- package/dist/x402/client.d.ts +72 -0
- package/dist/x402/client.d.ts.map +1 -0
- package/dist/x402/client.js +94 -0
- package/dist/x402/client.js.map +1 -0
- package/dist/x402/delegate-scheme.d.ts +107 -0
- package/dist/x402/delegate-scheme.d.ts.map +1 -0
- package/dist/x402/delegate-scheme.js +268 -0
- package/dist/x402/delegate-scheme.js.map +1 -0
- package/dist/x402/discovery.d.ts +110 -0
- package/dist/x402/discovery.d.ts.map +1 -0
- package/dist/x402/discovery.js +213 -0
- package/dist/x402/discovery.js.map +1 -0
- package/dist/x402/envelope.d.ts +65 -0
- package/dist/x402/envelope.d.ts.map +1 -0
- package/dist/x402/envelope.js +67 -0
- package/dist/x402/envelope.js.map +1 -0
- package/dist/x402/facilitator.d.ts +45 -0
- package/dist/x402/facilitator.d.ts.map +1 -0
- package/dist/x402/facilitator.js +61 -0
- package/dist/x402/facilitator.js.map +1 -0
- package/dist/x402/headers.d.ts +51 -0
- package/dist/x402/headers.d.ts.map +1 -0
- package/dist/x402/headers.js +84 -0
- package/dist/x402/headers.js.map +1 -0
- package/dist/x402/parse.d.ts +20 -0
- package/dist/x402/parse.d.ts.map +1 -0
- package/dist/x402/parse.js +31 -0
- package/dist/x402/parse.js.map +1 -0
- package/dist/x402/webhook.d.ts +48 -0
- package/dist/x402/webhook.d.ts.map +1 -0
- package/dist/x402/webhook.js +88 -0
- package/dist/x402/webhook.js.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Leash protocol fee primitives.
|
|
3
|
+
*
|
|
4
|
+
* Every Leash-flavoured x402 settlement levies a small protocol fee on
|
|
5
|
+
* top of the seller's quoted price. The buyer signs **one** transaction
|
|
6
|
+
* with **two** `TransferChecked` instructions — one to the seller's
|
|
7
|
+
* `payTo` ATA, one to the Leash treasury's ATA on the same mint — so
|
|
8
|
+
* both legs settle atomically (either both transfers land or neither
|
|
9
|
+
* does). The fee leg is funded out of the same source token account as
|
|
10
|
+
* the seller leg.
|
|
11
|
+
*
|
|
12
|
+
* This module is the shared building block:
|
|
13
|
+
* - {@link LEASH_FEE_BPS_DEFAULT} — 100 bps (1%) by default; overridable
|
|
14
|
+
* by env at the seller (which advertises the fee in `extra['leash.fee']`)
|
|
15
|
+
* and at the facilitator (which enforces it on `verify` / `settle`).
|
|
16
|
+
* - {@link computeFeeAtoms} — `ceilBps(amount, bps)`. Always rounds the
|
|
17
|
+
* fee **up** so dust never leaks out of the treasury when the buyer
|
|
18
|
+
* pays a non-divisible price.
|
|
19
|
+
* - {@link LeashFeeExtra} — wire shape stamped onto `paymentRequirements.extra`
|
|
20
|
+
* so buyer + facilitator agree on bps, amount, mint authority, and ATA.
|
|
21
|
+
* - {@link resolveLeashFeeAuthority} — env-driven lookup of the treasury
|
|
22
|
+
* authority pubkey per network (mainnet / devnet).
|
|
23
|
+
* - {@link getLeashFeeAtaFor} — derive the treasury's ATA for a given
|
|
24
|
+
* `(asset, tokenProgram)` pair so seller + facilitator both end up
|
|
25
|
+
* with the same destination address.
|
|
26
|
+
*
|
|
27
|
+
* Fee math is gross-up:
|
|
28
|
+
* - Seller quotes `net` (e.g. 1 USDC = 1_000_000 atoms).
|
|
29
|
+
* - Buyer pays `gross = net + fee` where `fee = ceil(net * bps / 10_000)`.
|
|
30
|
+
* - At 100 bps: 1 USDC → buyer signs 1.01 USDC; 1.00 USDC lands in seller
|
|
31
|
+
* ATA, 0.01 USDC lands in treasury ATA.
|
|
32
|
+
*
|
|
33
|
+
* Env vars (read at process boot — never inline a stale value):
|
|
34
|
+
* - `LEASH_FEE_BPS` — global default (integer 0..1000). Default 100.
|
|
35
|
+
* - `LEASH_FEE_ENFORCE` — `off | warn | enforce`. Default `warn`.
|
|
36
|
+
* - `LEASH_FEE_ENFORCE_MAINNET` — per-network override; falls back to LEASH_FEE_ENFORCE.
|
|
37
|
+
* - `LEASH_FEE_ENFORCE_DEVNET` — per-network override; falls back to LEASH_FEE_ENFORCE.
|
|
38
|
+
* - `LEASH_FEE_AUTHORITY_MAINNET`— wallet pubkey that owns the mainnet fee ATAs.
|
|
39
|
+
* - `LEASH_FEE_AUTHORITY_DEVNET` — wallet pubkey that owns the devnet fee ATAs.
|
|
40
|
+
*
|
|
41
|
+
* Defaults bake in `3DdcJkvjW7KLtMeko3Zr57jEJWhqRHuPsEBFm1XJYh7W` on both
|
|
42
|
+
* clusters so a fresh deploy collects fees out of the box. Override via
|
|
43
|
+
* env to rotate the treasury without code changes.
|
|
44
|
+
*/
|
|
45
|
+
import { address as toAddress } from '@solana/kit';
|
|
46
|
+
import { findAssociatedTokenPda, TOKEN_2022_PROGRAM_ADDRESS } from '@solana-program/token-2022';
|
|
47
|
+
import { TOKEN_PROGRAM_ADDRESS } from '@solana-program/token';
|
|
48
|
+
/**
|
|
49
|
+
* Default protocol fee rate in basis points (1 bps = 0.01%). 100 bps = 1%.
|
|
50
|
+
* Used by both the seller-kit (when stamping `extra['leash.fee']`) and
|
|
51
|
+
* the facilitator (when verifying inbound payment payloads). Override
|
|
52
|
+
* per-network via the `LEASH_FEE_BPS` env var on both surfaces.
|
|
53
|
+
*/
|
|
54
|
+
export const LEASH_FEE_BPS_DEFAULT = 100;
|
|
55
|
+
/**
|
|
56
|
+
* Default treasury authority on Solana mainnet. Owns the SPL token
|
|
57
|
+
* accounts (one ATA per stable mint) where Leash collects protocol fees.
|
|
58
|
+
* Set `LEASH_FEE_AUTHORITY_MAINNET` to override (e.g. when migrating to
|
|
59
|
+
* a multisig).
|
|
60
|
+
*/
|
|
61
|
+
export const LEASH_FEE_AUTHORITY_MAINNET_DEFAULT = '3DdcJkvjW7KLtMeko3Zr57jEJWhqRHuPsEBFm1XJYh7W';
|
|
62
|
+
/**
|
|
63
|
+
* Default treasury authority on Solana devnet. Same key as mainnet by
|
|
64
|
+
* design — devnet uses a separate ATA per mint anyway, so reusing the
|
|
65
|
+
* authority just simplifies operational tooling. Override via
|
|
66
|
+
* `LEASH_FEE_AUTHORITY_DEVNET`.
|
|
67
|
+
*/
|
|
68
|
+
export const LEASH_FEE_AUTHORITY_DEVNET_DEFAULT = '3DdcJkvjW7KLtMeko3Zr57jEJWhqRHuPsEBFm1XJYh7W';
|
|
69
|
+
/**
|
|
70
|
+
* Compute the fee in atomic units for a given seller amount + bps,
|
|
71
|
+
* rounding **up** (`ceil`) so dust never leaks out of the treasury.
|
|
72
|
+
*
|
|
73
|
+
* Examples (bps=100):
|
|
74
|
+
* - amount=1_000_000 → fee=10_000 (0.01 USDC for 1.00 USDC)
|
|
75
|
+
* - amount=1 → fee=1 (1 atom for 1 atom — ceil)
|
|
76
|
+
* - amount=999 → fee=10 (10 atoms for 999 atoms — ceil)
|
|
77
|
+
*
|
|
78
|
+
* @param amount seller leg amount in atomic units
|
|
79
|
+
* @param bps integer 0..10_000
|
|
80
|
+
* @returns atomic fee amount, never negative
|
|
81
|
+
*/
|
|
82
|
+
export function computeFeeAtoms(amount, bps) {
|
|
83
|
+
if (!Number.isInteger(bps) || bps < 0 || bps > 10_000) {
|
|
84
|
+
throw new Error(`computeFeeAtoms: bps must be integer in [0, 10000], got ${bps}`);
|
|
85
|
+
}
|
|
86
|
+
if (amount < 0n) {
|
|
87
|
+
throw new Error(`computeFeeAtoms: amount must be non-negative, got ${amount}`);
|
|
88
|
+
}
|
|
89
|
+
if (bps === 0 || amount === 0n)
|
|
90
|
+
return 0n;
|
|
91
|
+
const numerator = amount * BigInt(bps);
|
|
92
|
+
// Ceil division for positive integers: (n + d - 1) / d
|
|
93
|
+
return (numerator + 9999n) / 10000n;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Convenience: given a `net` (seller's quoted) amount, return the
|
|
97
|
+
* `(net, fee, gross)` triple where `gross = net + fee` and
|
|
98
|
+
* `fee = ceilBps(net, bps)`.
|
|
99
|
+
*
|
|
100
|
+
* Use at seller-kit's `buildAccepts` time and on the buyer playground
|
|
101
|
+
* UI to render "you will pay X" disclosures.
|
|
102
|
+
*/
|
|
103
|
+
export function applyFeeGrossUp(netAmount, bps = LEASH_FEE_BPS_DEFAULT) {
|
|
104
|
+
const fee = computeFeeAtoms(netAmount, bps);
|
|
105
|
+
return { net: netAmount, fee, gross: netAmount + fee };
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Read the configured fee bps from env. Falls back to
|
|
109
|
+
* {@link LEASH_FEE_BPS_DEFAULT} when unset / unparseable. Validates
|
|
110
|
+
* the range so a bad env never surfaces as a 50_000 bps fee.
|
|
111
|
+
*/
|
|
112
|
+
export function resolveLeashFeeBps() {
|
|
113
|
+
if (typeof process === 'undefined' || !process.env)
|
|
114
|
+
return LEASH_FEE_BPS_DEFAULT;
|
|
115
|
+
const raw = process.env.LEASH_FEE_BPS;
|
|
116
|
+
if (!raw)
|
|
117
|
+
return LEASH_FEE_BPS_DEFAULT;
|
|
118
|
+
const parsed = Number.parseInt(raw, 10);
|
|
119
|
+
if (!Number.isInteger(parsed) || parsed < 0 || parsed > 1_000) {
|
|
120
|
+
// Cap at 10% (1000 bps) for sanity — anything higher is almost
|
|
121
|
+
// certainly a misconfiguration.
|
|
122
|
+
return LEASH_FEE_BPS_DEFAULT;
|
|
123
|
+
}
|
|
124
|
+
return parsed;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Read the configured fee authority for the given network from env.
|
|
128
|
+
* Falls back to the bundled defaults
|
|
129
|
+
* ({@link LEASH_FEE_AUTHORITY_MAINNET_DEFAULT} /
|
|
130
|
+
* {@link LEASH_FEE_AUTHORITY_DEVNET_DEFAULT}) when unset.
|
|
131
|
+
*/
|
|
132
|
+
export function resolveLeashFeeAuthority(network) {
|
|
133
|
+
const envKey = network === 'mainnet' ? 'LEASH_FEE_AUTHORITY_MAINNET' : 'LEASH_FEE_AUTHORITY_DEVNET';
|
|
134
|
+
if (typeof process !== 'undefined' && process.env) {
|
|
135
|
+
const raw = process.env[envKey];
|
|
136
|
+
if (raw && raw.trim().length > 0)
|
|
137
|
+
return raw.trim();
|
|
138
|
+
}
|
|
139
|
+
return network === 'mainnet'
|
|
140
|
+
? LEASH_FEE_AUTHORITY_MAINNET_DEFAULT
|
|
141
|
+
: LEASH_FEE_AUTHORITY_DEVNET_DEFAULT;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Read the enforcement mode for the given network from env. Per-network
|
|
145
|
+
* vars override the global one. Default is `warn` everywhere so the
|
|
146
|
+
* rollout doesn't break older clients overnight.
|
|
147
|
+
*/
|
|
148
|
+
export function resolveLeashFeeEnforcement(network) {
|
|
149
|
+
if (typeof process === 'undefined' || !process.env)
|
|
150
|
+
return 'warn';
|
|
151
|
+
const perNetwork = network === 'mainnet'
|
|
152
|
+
? process.env.LEASH_FEE_ENFORCE_MAINNET
|
|
153
|
+
: process.env.LEASH_FEE_ENFORCE_DEVNET;
|
|
154
|
+
const global = process.env.LEASH_FEE_ENFORCE;
|
|
155
|
+
const raw = (perNetwork ?? global ?? 'warn').trim().toLowerCase();
|
|
156
|
+
if (raw === 'off' || raw === 'warn' || raw === 'enforce')
|
|
157
|
+
return raw;
|
|
158
|
+
return 'warn';
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Derive the Leash fee ATA on the given `(network, asset, tokenProgram)`.
|
|
162
|
+
* Both the seller (when stamping `extra['leash.fee'].feeDestination`)
|
|
163
|
+
* and the facilitator (when verifying the second `TransferChecked`)
|
|
164
|
+
* call this so they always agree on the destination.
|
|
165
|
+
*/
|
|
166
|
+
export async function getLeashFeeAtaFor(args) {
|
|
167
|
+
const authority = (args.authority ?? resolveLeashFeeAuthority(args.network));
|
|
168
|
+
const tokenProgram = args.tokenProgram === 'spl-token-2022' ? TOKEN_2022_PROGRAM_ADDRESS : TOKEN_PROGRAM_ADDRESS;
|
|
169
|
+
const [ata] = await findAssociatedTokenPda({
|
|
170
|
+
mint: toAddress(args.asset),
|
|
171
|
+
owner: toAddress(authority),
|
|
172
|
+
tokenProgram,
|
|
173
|
+
});
|
|
174
|
+
return { ata, authority: toAddress(authority) };
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Build the static `extra['leash.fee']` payload for a given seller leg.
|
|
178
|
+
*
|
|
179
|
+
* Sync by construction: the wire shape only carries `bps` and
|
|
180
|
+
* `feeAuthority`, so seller-kit / payment-links can stamp this at
|
|
181
|
+
* `buildAccepts` time without making `createSeller` async. The buyer +
|
|
182
|
+
* facilitator derive the dynamic fields (`feeAtomic`, `grossAtomic`,
|
|
183
|
+
* `feeDestination`) on demand via {@link computeLeashFeeForRequirements}.
|
|
184
|
+
*/
|
|
185
|
+
export function buildLeashFeeExtra(args) {
|
|
186
|
+
const bps = args.bps ?? resolveLeashFeeBps();
|
|
187
|
+
const feeAuthority = args.authority ?? resolveLeashFeeAuthority(args.network);
|
|
188
|
+
return { v: '1', bps, feeAuthority };
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Type guard + parser for an inbound `extra['leash.fee']` block. Returns
|
|
192
|
+
* `null` if the value is absent or malformed (any field missing /
|
|
193
|
+
* wrong type / out-of-range bps). Facilitators use this to decide whether
|
|
194
|
+
* to apply fee verification.
|
|
195
|
+
*/
|
|
196
|
+
export function parseLeashFeeExtra(extra) {
|
|
197
|
+
if (!extra || typeof extra !== 'object')
|
|
198
|
+
return null;
|
|
199
|
+
const raw = extra['leash.fee'];
|
|
200
|
+
if (!raw || typeof raw !== 'object')
|
|
201
|
+
return null;
|
|
202
|
+
const obj = raw;
|
|
203
|
+
if (obj.v !== '1')
|
|
204
|
+
return null;
|
|
205
|
+
const { bps, feeAuthority } = obj;
|
|
206
|
+
if (typeof bps !== 'number' ||
|
|
207
|
+
!Number.isInteger(bps) ||
|
|
208
|
+
bps < 0 ||
|
|
209
|
+
bps > 10_000 ||
|
|
210
|
+
typeof feeAuthority !== 'string' ||
|
|
211
|
+
feeAuthority.length === 0) {
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
return { v: '1', bps, feeAuthority };
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Resolve the per-request fee triple `(bps, feeAtomic, feeDestination)`
|
|
218
|
+
* for a given `paymentRequirements` entry. Returns `null` if the
|
|
219
|
+
* requirement carries no `extra['leash.fee']` (vanilla x402 mode).
|
|
220
|
+
*
|
|
221
|
+
* Both the buyer (when constructing the `TransferChecked` fee leg) and
|
|
222
|
+
* the facilitator (when verifying the inbound transaction) call this
|
|
223
|
+
* function so they always derive the same destination ATA + atomic
|
|
224
|
+
* amount from the same inputs.
|
|
225
|
+
*/
|
|
226
|
+
export async function computeLeashFeeForRequirements(args) {
|
|
227
|
+
if (!args.extra)
|
|
228
|
+
return null;
|
|
229
|
+
const bps = args.extra.bps;
|
|
230
|
+
const net = BigInt(args.amount);
|
|
231
|
+
const fee = computeFeeAtoms(net, bps);
|
|
232
|
+
const acct = await getLeashFeeAtaFor({
|
|
233
|
+
network: args.network,
|
|
234
|
+
asset: args.asset,
|
|
235
|
+
tokenProgram: args.tokenProgram,
|
|
236
|
+
authority: args.extra.feeAuthority,
|
|
237
|
+
});
|
|
238
|
+
return {
|
|
239
|
+
bps,
|
|
240
|
+
feeAtomic: fee,
|
|
241
|
+
grossAtomic: net + fee,
|
|
242
|
+
feeAuthority: acct.authority,
|
|
243
|
+
feeDestination: acct.ata,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
//# sourceMappingURL=leash-fee.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"leash-fee.js","sourceRoot":"","sources":["../../src/fees/leash-fee.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token-aware amount formatting / parsing helpers shared by every Leash UI
|
|
3
|
+
* surface (web playground, CLI demos) and downstream consumers.
|
|
4
|
+
*
|
|
5
|
+
* The fundamental invariant: **on the wire, amounts are integer strings in
|
|
6
|
+
* the token's atomic unit** (e.g. 1 USDC = `"1000000"` because USDC has 6
|
|
7
|
+
* decimals). Decimal display ("1.50 USDC") is a UI concern only and must
|
|
8
|
+
* be derived from the mint's `decimals`. Hand-rolling `*1_000_000` math
|
|
9
|
+
* silently breaks for Token-2022 stables with different decimal counts;
|
|
10
|
+
* always pass the right `decimals` here.
|
|
11
|
+
*/
|
|
12
|
+
import type { ReceiptV1 } from '@leashmarket/schemas';
|
|
13
|
+
import { type TokenNetwork } from '../tokens/index.js';
|
|
14
|
+
/**
|
|
15
|
+
* Convert an atomic integer string (or bigint) to its decimal string form.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* atomicToDecimal('1000000', 6) // '1'
|
|
19
|
+
* atomicToDecimal('1234500', 6) // '1.2345'
|
|
20
|
+
* atomicToDecimal('2', 6) // '0.000002'
|
|
21
|
+
*/
|
|
22
|
+
export declare function atomicToDecimal(amount: bigint | string, decimals: number): string;
|
|
23
|
+
/**
|
|
24
|
+
* Convert a decimal string ("1.50") to its atomic integer (1500000n at 6
|
|
25
|
+
* decimals). Returns `null` for malformed input — callers should treat
|
|
26
|
+
* `null` as "leave the amount field blank, don't proceed".
|
|
27
|
+
*
|
|
28
|
+
* Rejects more decimal places than the token supports rather than silently
|
|
29
|
+
* truncating, because losing dust to rounding when sending stablecoins is
|
|
30
|
+
* a user-trust bug.
|
|
31
|
+
*/
|
|
32
|
+
export declare function decimalToAtomic(input: string, decimals: number): bigint | null;
|
|
33
|
+
/**
|
|
34
|
+
* Format a `ReceiptV1.price` for UI display. Atomic integer amounts are
|
|
35
|
+
* resolved through the {@link KNOWN_TOKENS} registry when an `asset` mint is
|
|
36
|
+
* present; otherwise we fall back to USDC's 6 decimals (the playground
|
|
37
|
+
* default). Already-decimal strings (legacy receipts) pass through.
|
|
38
|
+
*/
|
|
39
|
+
export declare function formatReceiptPrice(price: ReceiptV1['price'] | undefined | null, network?: TokenNetwork): string | null;
|
|
40
|
+
/** {@link formatReceiptPrice} + the currency ticker. */
|
|
41
|
+
export declare function formatReceiptPriceWithCurrency(price: ReceiptV1['price'] | undefined | null, network?: TokenNetwork): string | null;
|
|
42
|
+
/**
|
|
43
|
+
* USD-style display ("$1.23", "$0.001000") for stablecoin prices. Falls back
|
|
44
|
+
* to {@link formatReceiptPriceWithCurrency} for non-stable currencies. Pad
|
|
45
|
+
* the fractional part to **at least 2 decimals** so `$1` doesn't read as
|
|
46
|
+
* truncated; preserve the long tail for sub-cent amounts so users see
|
|
47
|
+
* exactly what they paid.
|
|
48
|
+
*/
|
|
49
|
+
export declare function formatReceiptPriceUsd(price: ReceiptV1['price'] | undefined | null, network?: TokenNetwork): string | null;
|
|
50
|
+
/**
|
|
51
|
+
* Format a raw atomic balance against a known mint. Convenience wrapper
|
|
52
|
+
* around {@link atomicToDecimal} that sources `decimals` from the registry.
|
|
53
|
+
*/
|
|
54
|
+
export declare function formatTokenBalance(amount: bigint | string, mint: string, network: TokenNetwork): string;
|
|
55
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/format/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAKpE;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAajF;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAU9E;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,EAC5C,OAAO,GAAE,YAAuB,GAC/B,MAAM,GAAG,IAAI,CAMf;AAED,wDAAwD;AACxD,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,EAC5C,OAAO,GAAE,YAAuB,GAC/B,MAAM,GAAG,IAAI,CAKf;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,EAC5C,OAAO,GAAE,YAAuB,GAC/B,MAAM,GAAG,IAAI,CASf;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,YAAY,GACpB,MAAM,CAIR"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token-aware amount formatting / parsing helpers shared by every Leash UI
|
|
3
|
+
* surface (web playground, CLI demos) and downstream consumers.
|
|
4
|
+
*
|
|
5
|
+
* The fundamental invariant: **on the wire, amounts are integer strings in
|
|
6
|
+
* the token's atomic unit** (e.g. 1 USDC = `"1000000"` because USDC has 6
|
|
7
|
+
* decimals). Decimal display ("1.50 USDC") is a UI concern only and must
|
|
8
|
+
* be derived from the mint's `decimals`. Hand-rolling `*1_000_000` math
|
|
9
|
+
* silently breaks for Token-2022 stables with different decimal counts;
|
|
10
|
+
* always pass the right `decimals` here.
|
|
11
|
+
*/
|
|
12
|
+
import { lookupToken } from '../tokens/index.js';
|
|
13
|
+
/** USD-pegged stablecoin tickers shown with `$` prefix in {@link formatAmountUsd}. */
|
|
14
|
+
const STABLES = new Set(['USDC', 'USDT', 'USDG', 'PYUSD']);
|
|
15
|
+
/**
|
|
16
|
+
* Convert an atomic integer string (or bigint) to its decimal string form.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* atomicToDecimal('1000000', 6) // '1'
|
|
20
|
+
* atomicToDecimal('1234500', 6) // '1.2345'
|
|
21
|
+
* atomicToDecimal('2', 6) // '0.000002'
|
|
22
|
+
*/
|
|
23
|
+
export function atomicToDecimal(amount, decimals) {
|
|
24
|
+
const raw = typeof amount === 'bigint' ? amount.toString() : amount.trim();
|
|
25
|
+
if (!/^\d+$/.test(raw)) {
|
|
26
|
+
throw new Error(`atomicToDecimal: expected integer string, got "${raw}"`);
|
|
27
|
+
}
|
|
28
|
+
if (decimals < 0 || !Number.isInteger(decimals)) {
|
|
29
|
+
throw new Error(`atomicToDecimal: decimals must be a non-negative integer (got ${decimals})`);
|
|
30
|
+
}
|
|
31
|
+
if (decimals === 0)
|
|
32
|
+
return raw;
|
|
33
|
+
const padded = raw.padStart(decimals + 1, '0');
|
|
34
|
+
const whole = padded.slice(0, -decimals);
|
|
35
|
+
const frac = padded.slice(-decimals).replace(/0+$/, '');
|
|
36
|
+
return frac ? `${whole}.${frac}` : whole;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Convert a decimal string ("1.50") to its atomic integer (1500000n at 6
|
|
40
|
+
* decimals). Returns `null` for malformed input — callers should treat
|
|
41
|
+
* `null` as "leave the amount field blank, don't proceed".
|
|
42
|
+
*
|
|
43
|
+
* Rejects more decimal places than the token supports rather than silently
|
|
44
|
+
* truncating, because losing dust to rounding when sending stablecoins is
|
|
45
|
+
* a user-trust bug.
|
|
46
|
+
*/
|
|
47
|
+
export function decimalToAtomic(input, decimals) {
|
|
48
|
+
const s = input.trim();
|
|
49
|
+
if (!s)
|
|
50
|
+
return null;
|
|
51
|
+
const m = s.match(/^(\d+)(?:\.(\d+))?$/);
|
|
52
|
+
if (!m)
|
|
53
|
+
return null;
|
|
54
|
+
const whole = m[1] ?? '0';
|
|
55
|
+
const fracRaw = m[2] ?? '';
|
|
56
|
+
if (fracRaw.length > decimals)
|
|
57
|
+
return null;
|
|
58
|
+
const frac = fracRaw.padEnd(decimals, '0');
|
|
59
|
+
return BigInt(whole) * BigInt(10) ** BigInt(decimals) + BigInt(frac || '0');
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Format a `ReceiptV1.price` for UI display. Atomic integer amounts are
|
|
63
|
+
* resolved through the {@link KNOWN_TOKENS} registry when an `asset` mint is
|
|
64
|
+
* present; otherwise we fall back to USDC's 6 decimals (the playground
|
|
65
|
+
* default). Already-decimal strings (legacy receipts) pass through.
|
|
66
|
+
*/
|
|
67
|
+
export function formatReceiptPrice(price, network = 'devnet') {
|
|
68
|
+
if (!price)
|
|
69
|
+
return null;
|
|
70
|
+
const { amount, currency, asset } = price;
|
|
71
|
+
if (!/^\d+$/.test(amount))
|
|
72
|
+
return amount;
|
|
73
|
+
const decimals = resolveDecimals({ asset, currency, network });
|
|
74
|
+
return atomicToDecimal(amount, decimals);
|
|
75
|
+
}
|
|
76
|
+
/** {@link formatReceiptPrice} + the currency ticker. */
|
|
77
|
+
export function formatReceiptPriceWithCurrency(price, network = 'devnet') {
|
|
78
|
+
if (!price)
|
|
79
|
+
return null;
|
|
80
|
+
const core = formatReceiptPrice(price, network);
|
|
81
|
+
if (core === null)
|
|
82
|
+
return null;
|
|
83
|
+
return `${core} ${price.currency}`;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* USD-style display ("$1.23", "$0.001000") for stablecoin prices. Falls back
|
|
87
|
+
* to {@link formatReceiptPriceWithCurrency} for non-stable currencies. Pad
|
|
88
|
+
* the fractional part to **at least 2 decimals** so `$1` doesn't read as
|
|
89
|
+
* truncated; preserve the long tail for sub-cent amounts so users see
|
|
90
|
+
* exactly what they paid.
|
|
91
|
+
*/
|
|
92
|
+
export function formatReceiptPriceUsd(price, network = 'devnet') {
|
|
93
|
+
if (!price)
|
|
94
|
+
return null;
|
|
95
|
+
if (!STABLES.has(price.currency))
|
|
96
|
+
return formatReceiptPriceWithCurrency(price, network);
|
|
97
|
+
const core = formatReceiptPrice(price, network);
|
|
98
|
+
if (core === null)
|
|
99
|
+
return null;
|
|
100
|
+
if (/^\d+$/.test(core))
|
|
101
|
+
return `$${core}.00`;
|
|
102
|
+
const [whole, frac = ''] = core.split('.');
|
|
103
|
+
if (frac.length < 2)
|
|
104
|
+
return `$${whole}.${frac.padEnd(2, '0')}`;
|
|
105
|
+
return `$${core}`;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Format a raw atomic balance against a known mint. Convenience wrapper
|
|
109
|
+
* around {@link atomicToDecimal} that sources `decimals` from the registry.
|
|
110
|
+
*/
|
|
111
|
+
export function formatTokenBalance(amount, mint, network) {
|
|
112
|
+
const token = lookupToken(mint, network);
|
|
113
|
+
const decimals = token?.decimals ?? 0;
|
|
114
|
+
return atomicToDecimal(amount, decimals);
|
|
115
|
+
}
|
|
116
|
+
function resolveDecimals(args) {
|
|
117
|
+
if (args.asset) {
|
|
118
|
+
const known = lookupToken(args.asset, args.network);
|
|
119
|
+
if (known)
|
|
120
|
+
return known.decimals;
|
|
121
|
+
}
|
|
122
|
+
// Stablecoins are 6 decimals on Solana (USDC/USDT/USDG/PYUSD).
|
|
123
|
+
if (STABLES.has(args.currency))
|
|
124
|
+
return 6;
|
|
125
|
+
// Unknown non-stablecoins: leave atomic untouched. Better to show "5 BONK"
|
|
126
|
+
// than silently divide by 1e6 and surface "0.000005 BONK" — which would be
|
|
127
|
+
// a misleading payment amount in receipts.
|
|
128
|
+
return 0;
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/format/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export * from './agent/agent.js';
|
|
2
|
+
export * from './agent/treasury-pda.js';
|
|
3
|
+
export * from './policy/evaluate.js';
|
|
4
|
+
export * from './policy/state.js';
|
|
5
|
+
export * from './receipt/hash.js';
|
|
6
|
+
export * from './receipt/build.js';
|
|
7
|
+
export * from './receipt/verify.js';
|
|
8
|
+
export * from './x402/client.js';
|
|
9
|
+
export * from './x402/discovery.js';
|
|
10
|
+
export * from './x402/delegate-scheme.js';
|
|
11
|
+
export * from './x402/envelope.js';
|
|
12
|
+
export * from './x402/facilitator.js';
|
|
13
|
+
export * from './x402/headers.js';
|
|
14
|
+
export * from './x402/parse.js';
|
|
15
|
+
export * from './x402/webhook.js';
|
|
16
|
+
export * from './treasury/balance.js';
|
|
17
|
+
export * from './treasury/inspect-token-account.js';
|
|
18
|
+
export * from './treasury/list-balances.js';
|
|
19
|
+
export * from './treasury/pause.js';
|
|
20
|
+
export * from './tokens/index.js';
|
|
21
|
+
export * from './fees/leash-fee.js';
|
|
22
|
+
export * from './explorer/index.js';
|
|
23
|
+
export * from './format/index.js';
|
|
24
|
+
export * from './wallet/index.js';
|
|
25
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qCAAqC,CAAC;AACpD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export * from './agent/agent.js';
|
|
2
|
+
export * from './agent/treasury-pda.js';
|
|
3
|
+
export * from './policy/evaluate.js';
|
|
4
|
+
export * from './policy/state.js';
|
|
5
|
+
export * from './receipt/hash.js';
|
|
6
|
+
export * from './receipt/build.js';
|
|
7
|
+
export * from './receipt/verify.js';
|
|
8
|
+
export * from './x402/client.js';
|
|
9
|
+
export * from './x402/discovery.js';
|
|
10
|
+
export * from './x402/delegate-scheme.js';
|
|
11
|
+
export * from './x402/envelope.js';
|
|
12
|
+
export * from './x402/facilitator.js';
|
|
13
|
+
export * from './x402/headers.js';
|
|
14
|
+
export * from './x402/parse.js';
|
|
15
|
+
export * from './x402/webhook.js';
|
|
16
|
+
export * from './treasury/balance.js';
|
|
17
|
+
export * from './treasury/inspect-token-account.js';
|
|
18
|
+
export * from './treasury/list-balances.js';
|
|
19
|
+
export * from './treasury/pause.js';
|
|
20
|
+
export * from './tokens/index.js';
|
|
21
|
+
export * from './fees/leash-fee.js';
|
|
22
|
+
export * from './explorer/index.js';
|
|
23
|
+
export * from './format/index.js';
|
|
24
|
+
export * from './wallet/index.js';
|
|
25
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qCAAqC,CAAC;AACpD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { RulesV1 } from '@leashmarket/schemas';
|
|
2
|
+
import type { PolicyState } from './state.js';
|
|
3
|
+
export type PolicyRequest = {
|
|
4
|
+
method: string;
|
|
5
|
+
url: string;
|
|
6
|
+
estimatedPrice?: string;
|
|
7
|
+
requestHash: string;
|
|
8
|
+
};
|
|
9
|
+
export type PolicyDecision = {
|
|
10
|
+
decision: 'allow';
|
|
11
|
+
} | {
|
|
12
|
+
decision: 'deny';
|
|
13
|
+
reason: string;
|
|
14
|
+
};
|
|
15
|
+
/** Pure policy gate — no IO. */
|
|
16
|
+
export declare function evaluate(req: PolicyRequest, rules: RulesV1, state: PolicyState): PolicyDecision;
|
|
17
|
+
//# sourceMappingURL=evaluate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evaluate.d.ts","sourceRoot":"","sources":["../../src/policy/evaluate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAAE,QAAQ,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAc1F,gCAAgC;AAChC,wBAAgB,QAAQ,CAAC,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,GAAG,cAAc,CAiC/F"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
function cmpDecimal(a, b) {
|
|
2
|
+
return Number.parseFloat(a) - Number.parseFloat(b);
|
|
3
|
+
}
|
|
4
|
+
function hostFromUrl(url) {
|
|
5
|
+
try {
|
|
6
|
+
return new URL(url).hostname;
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
return '';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/** Pure policy gate — no IO. */
|
|
13
|
+
export function evaluate(req, rules, state) {
|
|
14
|
+
if (state.recentRequestHashes.includes(req.requestHash)) {
|
|
15
|
+
return { decision: 'deny', reason: 'replay' };
|
|
16
|
+
}
|
|
17
|
+
const host = hostFromUrl(req.url);
|
|
18
|
+
if (rules.hosts.deny?.some((h) => host === h || host.endsWith(`.${h}`))) {
|
|
19
|
+
return { decision: 'deny', reason: 'denyHost' };
|
|
20
|
+
}
|
|
21
|
+
if (rules.hosts.allow && rules.hosts.allow.length > 0) {
|
|
22
|
+
const ok = rules.hosts.allow.some((h) => host === h || host.endsWith(`.${h}`));
|
|
23
|
+
if (!ok) {
|
|
24
|
+
return { decision: 'deny', reason: 'allowHost' };
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if (req.estimatedPrice && rules.priceCeiling) {
|
|
28
|
+
if (cmpDecimal(req.estimatedPrice, rules.priceCeiling) > 0) {
|
|
29
|
+
return { decision: 'deny', reason: 'priceCeiling' };
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const nextSpend = req.estimatedPrice !== undefined
|
|
33
|
+
? String(Number.parseFloat(state.spentToday) + Number.parseFloat(req.estimatedPrice))
|
|
34
|
+
: state.spentToday;
|
|
35
|
+
if (cmpDecimal(state.spentToday, rules.budget.daily) > 0) {
|
|
36
|
+
return { decision: 'deny', reason: 'dailyBudgetExceeded' };
|
|
37
|
+
}
|
|
38
|
+
if (cmpDecimal(nextSpend, rules.budget.daily) > 0) {
|
|
39
|
+
return { decision: 'deny', reason: 'dailyBudgetExceeded' };
|
|
40
|
+
}
|
|
41
|
+
if (req.estimatedPrice && cmpDecimal(req.estimatedPrice, rules.budget.perCall) > 0) {
|
|
42
|
+
return { decision: 'deny', reason: 'perCallMax' };
|
|
43
|
+
}
|
|
44
|
+
return { decision: 'allow' };
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=evaluate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evaluate.js","sourceRoot":"","sources":["../../src/policy/evaluate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { RulesV1 } from '@leashmarket/schemas';
|
|
2
|
+
export type PolicyState = {
|
|
3
|
+
rules: RulesV1;
|
|
4
|
+
/** Total spent today in minor units or decimal string — v0.1 uses string decimal for simplicity. */
|
|
5
|
+
spentToday: string;
|
|
6
|
+
recentRequestHashes: string[];
|
|
7
|
+
};
|
|
8
|
+
//# sourceMappingURL=state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/policy/state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAEpD,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,OAAO,CAAC;IACf,oGAAoG;IACpG,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB,EAAE,MAAM,EAAE,CAAC;CAC/B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/policy/state.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ReceiptV1 } from '@leashmarket/schemas';
|
|
2
|
+
export type ReceiptDraft = Omit<ReceiptV1, 'receipt_hash'>;
|
|
3
|
+
export declare function computeReceiptHash(draft: ReceiptDraft): string;
|
|
4
|
+
export declare function finalizeReceipt(draft: ReceiptDraft): ReceiptV1;
|
|
5
|
+
//# sourceMappingURL=build.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/receipt/build.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAGtD,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;AAE3D,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAE9D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG,SAAS,CAG9D"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { canonicalJson, sha256Hex } from './hash.js';
|
|
2
|
+
export function computeReceiptHash(draft) {
|
|
3
|
+
return sha256Hex(canonicalJson(draft));
|
|
4
|
+
}
|
|
5
|
+
export function finalizeReceipt(draft) {
|
|
6
|
+
const receipt_hash = computeReceiptHash(draft);
|
|
7
|
+
return { ...draft, receipt_hash };
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=build.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/receipt/build.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAIrD,MAAM,UAAU,kBAAkB,CAAC,KAAmB;IACpD,OAAO,SAAS,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAmB;IACjD,MAAM,YAAY,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAC/C,OAAO,EAAE,GAAG,KAAK,EAAE,YAAY,EAAE,CAAC;AACpC,CAAC"}
|