@1sat/wallet-server 0.0.1 → 0.0.3

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.
Files changed (51) hide show
  1. package/dist/accounts/index.d.ts +4 -7
  2. package/dist/accounts/index.d.ts.map +1 -1
  3. package/dist/accounts/index.js +3 -6
  4. package/dist/accounts/index.js.map +1 -1
  5. package/dist/accounts/middleware.d.ts +29 -30
  6. package/dist/accounts/middleware.d.ts.map +1 -1
  7. package/dist/accounts/middleware.js +303 -121
  8. package/dist/accounts/middleware.js.map +1 -1
  9. package/dist/accounts/pricing.d.ts +38 -11
  10. package/dist/accounts/pricing.d.ts.map +1 -1
  11. package/dist/accounts/pricing.js +40 -11
  12. package/dist/accounts/pricing.js.map +1 -1
  13. package/dist/accounts/queries.d.ts +42 -0
  14. package/dist/accounts/queries.d.ts.map +1 -0
  15. package/dist/accounts/queries.js +91 -0
  16. package/dist/accounts/queries.js.map +1 -0
  17. package/dist/accounts/types.d.ts +46 -29
  18. package/dist/accounts/types.d.ts.map +1 -1
  19. package/dist/client.d.ts +20 -0
  20. package/dist/client.d.ts.map +1 -0
  21. package/dist/client.js +34 -0
  22. package/dist/client.js.map +1 -0
  23. package/dist/createWalletServer.d.ts +12 -3
  24. package/dist/createWalletServer.d.ts.map +1 -1
  25. package/dist/createWalletServer.js +84 -46
  26. package/dist/createWalletServer.js.map +1 -1
  27. package/dist/index.d.ts +3 -0
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +2 -0
  30. package/dist/index.js.map +1 -1
  31. package/dist/topUp.d.ts +28 -0
  32. package/dist/topUp.d.ts.map +1 -0
  33. package/dist/topUp.js +67 -0
  34. package/dist/topUp.js.map +1 -0
  35. package/package.json +57 -46
  36. package/dist/accounts/metering.d.ts +0 -15
  37. package/dist/accounts/metering.d.ts.map +0 -1
  38. package/dist/accounts/metering.js +0 -32
  39. package/dist/accounts/metering.js.map +0 -1
  40. package/dist/accounts/migrations.d.ts +0 -18
  41. package/dist/accounts/migrations.d.ts.map +0 -1
  42. package/dist/accounts/migrations.js +0 -46
  43. package/dist/accounts/migrations.js.map +0 -1
  44. package/dist/accounts/paymentValidation.d.ts +0 -59
  45. package/dist/accounts/paymentValidation.d.ts.map +0 -1
  46. package/dist/accounts/paymentValidation.js +0 -112
  47. package/dist/accounts/paymentValidation.js.map +0 -1
  48. package/dist/accounts/repo.d.ts +0 -17
  49. package/dist/accounts/repo.d.ts.map +0 -1
  50. package/dist/accounts/repo.js +0 -94
  51. package/dist/accounts/repo.js.map +0 -1
@@ -1,8 +1,5 @@
1
- export type { Account, AccountsConfig, IdentityKey, NewPayment, Payment, PaymentQuote, } from './types';
2
- export { AccountsRepo } from './repo';
3
- export { ACCOUNTS_TABLE, PAYMENTS_TABLE, runMigrations, up, down, } from './migrations';
4
- export { measureUsedBytes } from './metering';
5
- export { BYTES_PER_GB, computeCapacity, priceForDeficit, quoteForAccount, type CapacityInput, type CapacityResult, } from './pricing';
6
- export { BRC0121_HEADERS, Brc0121PaymentError, internalizePayment, parseBrc0121Payment, readBrc0121Headers, validateBrc0121Payment, type Brc0121PaymentHeaders, type ParsedPayment, type ValidatePaymentInput, type ValidatePaymentResult, } from './paymentValidation';
7
- export { AccountsGate, type AccountsMiddlewareDeps, type BillabilityCheckInput, type BillabilityDecision, } from './middleware';
1
+ export type { AccountStatusResponse, AccountsConfig, IdentityKey, NextPaymentDerivation, } from './types';
2
+ export { BYTES_PER_GB, computeCapacity, quoteRefundedCharge, refundCreditSats, type CapacityInput, type CapacityResult, type RefundedQuote, type RefundedQuoteInput, } from './pricing';
3
+ export { type AccountsMiddlewareDeps, accountsCapacityGate, ERR_INSUFFICIENT_CAPACITY, nextPaymentDerivation, } from './middleware';
4
+ export { type PaymentRecord, PAYMENT_LABEL, blockLabel, bytesLabel, countPaymentsForPayer, latestActivePaymentForPayer, listPaymentsForPayer, payerLabel, } from './queries';
8
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/accounts/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACX,OAAO,EACP,cAAc,EACd,WAAW,EACX,UAAU,EACV,OAAO,EACP,YAAY,GACZ,MAAM,SAAS,CAAA;AAEhB,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,EACN,cAAc,EACd,cAAc,EACd,aAAa,EACb,EAAE,EACF,IAAI,GACJ,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAC7C,OAAO,EACN,YAAY,EACZ,eAAe,EACf,eAAe,EACf,eAAe,EACf,KAAK,aAAa,EAClB,KAAK,cAAc,GACnB,MAAM,WAAW,CAAA;AAClB,OAAO,EACN,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,GAC1B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACN,YAAY,EACZ,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,GACxB,MAAM,cAAc,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/accounts/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACX,qBAAqB,EACrB,cAAc,EACd,WAAW,EACX,qBAAqB,GACrB,MAAM,SAAS,CAAA;AAEhB,OAAO,EACN,YAAY,EACZ,eAAe,EACf,mBAAmB,EACnB,gBAAgB,EAChB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,kBAAkB,GACvB,MAAM,WAAW,CAAA;AAClB,OAAO,EACN,KAAK,sBAAsB,EAC3B,oBAAoB,EACpB,yBAAyB,EACzB,qBAAqB,GACrB,MAAM,cAAc,CAAA;AACrB,OAAO,EACN,KAAK,aAAa,EAClB,aAAa,EACb,UAAU,EACV,UAAU,EACV,qBAAqB,EACrB,2BAA2B,EAC3B,oBAAoB,EACpB,UAAU,GACV,MAAM,WAAW,CAAA"}
@@ -1,7 +1,4 @@
1
- export { AccountsRepo } from './repo';
2
- export { ACCOUNTS_TABLE, PAYMENTS_TABLE, runMigrations, up, down, } from './migrations';
3
- export { measureUsedBytes } from './metering';
4
- export { BYTES_PER_GB, computeCapacity, priceForDeficit, quoteForAccount, } from './pricing';
5
- export { BRC0121_HEADERS, Brc0121PaymentError, internalizePayment, parseBrc0121Payment, readBrc0121Headers, validateBrc0121Payment, } from './paymentValidation';
6
- export { AccountsGate, } from './middleware';
1
+ export { BYTES_PER_GB, computeCapacity, quoteRefundedCharge, refundCreditSats, } from './pricing';
2
+ export { accountsCapacityGate, ERR_INSUFFICIENT_CAPACITY, nextPaymentDerivation, } from './middleware';
3
+ export { PAYMENT_LABEL, blockLabel, bytesLabel, countPaymentsForPayer, latestActivePaymentForPayer, listPaymentsForPayer, payerLabel, } from './queries';
7
4
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/accounts/index.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,EACN,cAAc,EACd,cAAc,EACd,aAAa,EACb,EAAE,EACF,IAAI,GACJ,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAC7C,OAAO,EACN,YAAY,EACZ,eAAe,EACf,eAAe,EACf,eAAe,GAGf,MAAM,WAAW,CAAA;AAClB,OAAO,EACN,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,GAKtB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACN,YAAY,GAIZ,MAAM,cAAc,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/accounts/index.ts"],"names":[],"mappings":"AAOA,OAAO,EACN,YAAY,EACZ,eAAe,EACf,mBAAmB,EACnB,gBAAgB,GAKhB,MAAM,WAAW,CAAA;AAClB,OAAO,EAEN,oBAAoB,EACpB,yBAAyB,EACzB,qBAAqB,GACrB,MAAM,cAAc,CAAA;AACrB,OAAO,EAEN,aAAa,EACb,UAAU,EACV,UAAU,EACV,qBAAqB,EACrB,2BAA2B,EAC3B,oBAAoB,EACpB,UAAU,GACV,MAAM,WAAW,CAAA"}
@@ -1,41 +1,40 @@
1
- import type { WalletInterface } from '@bsv/sdk';
2
- import type { Knex } from 'knex';
3
- import type { ResolvedIdentity, WalletStorageProvider } from '../types';
4
- import { AccountsRepo } from './repo';
5
- import type { AccountsConfig, IdentityKey } from './types';
1
+ /**
2
+ * Express middleware for the accounts layer.
3
+ *
4
+ * `accountsCapacityGate(deps)` runs between auth and dispatch. For
5
+ * billable methods (createAction / processAction), inspects the call for a
6
+ * valid self-payment output. If over-capacity, lets the call through only
7
+ * if a valid self-payment is present. If a valid self-payment is present on
8
+ * a `processAction`, schedules an auto-internalize after the response so
9
+ * the received payment gets recorded into the server's own wallet with the
10
+ * accounts-ledger labels. No separate `/account/payment` endpoint — one
11
+ * client call is enough.
12
+ */
13
+ import { type WalletInterface } from '@bsv/sdk';
14
+ import type { NextFunction, Request, Response } from 'express';
15
+ import type { WalletStorageProvider } from '../types';
16
+ import type { AccountsConfig, IdentityKey, NextPaymentDerivation } from './types';
17
+ /**
18
+ * Server-issued next-payment derivation for an identity. Prefix is constant;
19
+ * suffix is the monotonic count of payments already recorded for the
20
+ * identity (first payment uses "0").
21
+ */
22
+ export declare function nextPaymentDerivation(identityKey: IdentityKey, wallet: WalletInterface): Promise<NextPaymentDerivation>;
6
23
  export interface AccountsMiddlewareDeps {
7
24
  config: AccountsConfig;
8
25
  walletStorage: WalletStorageProvider;
9
- knex: Knex;
10
26
  wallet: WalletInterface;
11
27
  serverIdentityKey: IdentityKey;
12
28
  /** Returns the current chain tip block height. */
13
29
  currentBlock: () => Promise<number>;
14
30
  }
15
- export interface BillabilityCheckInput {
16
- method: string;
17
- identity: ResolvedIdentity;
18
- request: Request;
19
- id: string | number | null;
20
- }
21
- export type BillabilityDecision = {
22
- type: 'allow';
23
- } | {
24
- type: 'blocked';
25
- response: Response;
26
- };
31
+ /** JSON-RPC error code for "insufficient storage capacity". */
32
+ export declare const ERR_INSUFFICIENT_CAPACITY = -32005;
27
33
  /**
28
- * Gate that runs before dispatch for each JSON-RPC call. Decides whether to
29
- * allow the call, to return a 402 challenge, or to accept a payment and then
30
- * allow.
34
+ * Express middleware. Runs between auth and dispatch. For billable methods
35
+ * when the caller is over capacity, short-circuits with 507 + quota info.
36
+ * On processAction for a valid self-payment, schedules a post-response
37
+ * auto-internalize so the payment is recorded in the server's wallet.
31
38
  */
32
- export declare class AccountsGate {
33
- private readonly deps;
34
- readonly repo: AccountsRepo;
35
- private readonly freeKeys;
36
- constructor(deps: AccountsMiddlewareDeps);
37
- check(input: BillabilityCheckInput): Promise<BillabilityDecision>;
38
- private resolveUserId;
39
- private buildChallenge;
40
- }
39
+ export declare function accountsCapacityGate(deps: AccountsMiddlewareDeps): (req: Request, res: Response, next: NextFunction) => Promise<void | Response<any, Record<string, any>>>;
41
40
  //# sourceMappingURL=middleware.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/accounts/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAE/C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAEhC,OAAO,KAAK,EAEX,gBAAgB,EAChB,qBAAqB,EACrB,MAAM,UAAU,CAAA;AASjB,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAE1D,MAAM,WAAW,sBAAsB;IACtC,MAAM,EAAE,cAAc,CAAA;IACtB,aAAa,EAAE,qBAAqB,CAAA;IACpC,IAAI,EAAE,IAAI,CAAA;IACV,MAAM,EAAE,eAAe,CAAA;IACvB,iBAAiB,EAAE,WAAW,CAAA;IAC9B,kDAAkD;IAClD,YAAY,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;CACnC;AAED,MAAM,WAAW,qBAAqB;IACrC,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,OAAO,EAAE,OAAO,CAAA;IAChB,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;CAC1B;AAED,MAAM,MAAM,mBAAmB,GAC5B;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,CAAA;AAE1C;;;;GAIG;AACH,qBAAa,YAAY;IAIZ,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHjC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAA;IAC3B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkB;gBAEd,IAAI,EAAE,sBAAsB;IAQnD,KAAK,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,mBAAmB,CAAC;YAyEzD,aAAa;IAO3B,OAAO,CAAC,cAAc;CAmCtB"}
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/accounts/middleware.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAA0B,KAAK,eAAe,EAAS,MAAM,UAAU,CAAA;AAC9E,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAE9D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAA;AAUrD,OAAO,KAAK,EACX,cAAc,EACd,WAAW,EACX,qBAAqB,EACrB,MAAM,SAAS,CAAA;AAsEhB;;;;GAIG;AACH,wBAAsB,qBAAqB,CAC1C,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,eAAe,GACrB,OAAO,CAAC,qBAAqB,CAAC,CAMhC;AAED,MAAM,WAAW,sBAAsB;IACtC,MAAM,EAAE,cAAc,CAAA;IACtB,aAAa,EAAE,qBAAqB,CAAA;IACpC,MAAM,EAAE,eAAe,CAAA;IACvB,iBAAiB,EAAE,WAAW,CAAA;IAC9B,kDAAkD;IAClD,YAAY,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;CACnC;AAID,+DAA+D;AAC/D,eAAO,MAAM,yBAAyB,SAAS,CAAA;AA4M/C;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,sBAAsB,IAMlD,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,wDAoH7D"}
@@ -1,137 +1,319 @@
1
- import { Random, Utils } from '@bsv/sdk';
1
+ /**
2
+ * Express middleware for the accounts layer.
3
+ *
4
+ * `accountsCapacityGate(deps)` — runs between auth and dispatch. For
5
+ * billable methods (createAction / processAction), inspects the call for a
6
+ * valid self-payment output. If over-capacity, lets the call through only
7
+ * if a valid self-payment is present. If a valid self-payment is present on
8
+ * a `processAction`, schedules an auto-internalize after the response so
9
+ * the received payment gets recorded into the server's own wallet with the
10
+ * accounts-ledger labels. No separate `/account/payment` endpoint — one
11
+ * client call is enough.
12
+ */
13
+ import { P2PKH, PublicKey, Utils } from '@bsv/sdk';
2
14
  import { isBillableMethod } from '../dispatch';
3
- import { measureUsedBytes } from './metering';
4
- import { Brc0121PaymentError, internalizePayment, parseBrc0121Payment, readBrc0121Headers, } from './paymentValidation';
5
- import { BYTES_PER_GB, computeCapacity, priceForDeficit } from './pricing';
6
- import { AccountsRepo } from './repo';
15
+ import { quoteRefundedCharge } from './pricing';
16
+ import { PAYMENT_LABEL, blockLabel, bytesLabel, countPaymentsForPayer, latestActivePaymentForPayer, payerLabel, } from './queries';
17
+ /** BRC-29 protocol ID for wallet payments (matches @1sat/types constant). */
18
+ const BRC29_PROTOCOL_ID = [2, '3241645161d8'];
19
+ /** Static derivation prefix tag (before base64 encoding). */
20
+ const PAYMENT_DERIVATION_PREFIX_TAG = 'wallet-storage';
21
+ /** Cap on non-change outputs allowed in a bypassed createAction, to stop
22
+ * clients from smuggling unrelated work into the payment tx. */
23
+ const MAX_OUTPUTS_IN_BYPASSED_CREATE_ACTION = 2;
24
+ function toBase64Prefix(prefix) {
25
+ return Utils.toBase64(Array.from(new TextEncoder().encode(prefix)));
26
+ }
27
+ function toBase64Suffix(index) {
28
+ return Utils.toBase64([
29
+ (index >>> 24) & 0xff,
30
+ (index >>> 16) & 0xff,
31
+ (index >>> 8) & 0xff,
32
+ index & 0xff,
33
+ ]);
34
+ }
35
+ /**
36
+ * Server-issued next-payment derivation for an identity. Prefix is constant;
37
+ * suffix is the monotonic count of payments already recorded for the
38
+ * identity (first payment uses "0").
39
+ */
40
+ export async function nextPaymentDerivation(identityKey, wallet) {
41
+ const count = await countPaymentsForPayer(wallet, identityKey);
42
+ return {
43
+ derivationPrefix: toBase64Prefix(PAYMENT_DERIVATION_PREFIX_TAG),
44
+ derivationSuffix: toBase64Suffix(count),
45
+ };
46
+ }
47
+ /** JSON-RPC error code for "insufficient storage capacity". */
48
+ export const ERR_INSUFFICIENT_CAPACITY = -32005;
7
49
  /**
8
- * Gate that runs before dispatch for each JSON-RPC call. Decides whether to
9
- * allow the call, to return a 402 challenge, or to accept a payment and then
10
- * allow.
50
+ * Derive the P2PKH locking script that the sender is expected to pay to for
51
+ * the given derivation suffix. Uses the server wallet's BRC-29 key
52
+ * derivation — trust rooted entirely in server-side state.
11
53
  */
12
- export class AccountsGate {
13
- deps;
14
- repo;
15
- freeKeys;
16
- constructor(deps) {
17
- this.deps = deps;
18
- this.repo = new AccountsRepo(deps.knex);
19
- this.freeKeys = new Set([
20
- deps.serverIdentityKey,
21
- ...(deps.config.freeIdentityKeys ?? []),
22
- ]);
54
+ async function deriveExpectedPaymentScript(serverWallet, senderIdentityKey, expected) {
55
+ const { publicKey } = await serverWallet.getPublicKey({
56
+ protocolID: BRC29_PROTOCOL_ID,
57
+ keyID: `${expected.derivationPrefix} ${expected.derivationSuffix}`,
58
+ counterparty: senderIdentityKey,
59
+ forSelf: true,
60
+ });
61
+ const address = PublicKey.fromString(publicKey).toAddress();
62
+ return new P2PKH().lock(address).toHex();
63
+ }
64
+ /**
65
+ * Returns match info (output index + satoshis) iff this createAction
66
+ * describes a valid self-payment: has the `account-payment:<serverIdentity>`
67
+ * label, bounded outputs, one output matching the server's expected BRC-29
68
+ * script with satoshis ≥ minSats.
69
+ *
70
+ * Client-supplied customInstructions are never trusted — the expected script
71
+ * is derived purely from server state (identity keys + next suffix).
72
+ */
73
+ async function matchCreateActionPayment(params, senderIdentityKey, serverIdentityKey, serverWallet, expected, minSats) {
74
+ const args = (params?.[1] ?? {});
75
+ const labels = Array.isArray(args.labels) ? args.labels : [];
76
+ const expectedLabel = `account-payment:${serverIdentityKey}`;
77
+ if (!labels.includes(expectedLabel))
78
+ return undefined;
79
+ const outputs = Array.isArray(args.outputs)
80
+ ? args.outputs
81
+ : [];
82
+ if (outputs.length === 0 ||
83
+ outputs.length > MAX_OUTPUTS_IN_BYPASSED_CREATE_ACTION) {
84
+ return undefined;
85
+ }
86
+ let expectedScript;
87
+ try {
88
+ expectedScript = await deriveExpectedPaymentScript(serverWallet, senderIdentityKey, expected);
89
+ }
90
+ catch {
91
+ return undefined;
23
92
  }
24
- async check(input) {
25
- if (!this.deps.config.enabled)
26
- return { type: 'allow' };
27
- if (!isBillableMethod(input.method))
28
- return { type: 'allow' };
29
- if (this.freeKeys.has(input.identity.identityKey))
30
- return { type: 'allow' };
31
- const userId = await this.resolveUserId(input.identity.identityKey);
32
- if (userId == null) {
33
- // No wallet-toolbox user yet means zero bytes stored. Allow the first
34
- // billable request so the user row can be created; metering starts
35
- // from the next request.
36
- return { type: 'allow' };
93
+ for (let i = 0; i < outputs.length; i++) {
94
+ const output = outputs[i];
95
+ if (typeof output.lockingScript === 'string' &&
96
+ typeof output.satoshis === 'number' &&
97
+ output.lockingScript === expectedScript &&
98
+ output.satoshis >= minSats) {
99
+ return { outputIndex: i, satoshis: output.satoshis };
37
100
  }
38
- const currentBlock = await this.deps.currentBlock();
39
- const used = await measureUsedBytes(this.deps.knex, userId);
40
- const paidBytes = await this.repo.sumUnexpiredBytes(input.identity.identityKey, currentBlock);
41
- const capacity = computeCapacity({
42
- baselineBytes: this.deps.config.baselineBytes,
43
- paidBytes,
44
- usedBytes: used,
101
+ }
102
+ return undefined;
103
+ }
104
+ /**
105
+ * Returns match info iff this processAction refers to an action whose
106
+ * stored outputs contain a valid self-payment to the server. The action
107
+ * must belong to the authenticated user.
108
+ */
109
+ async function matchProcessActionPayment(params, senderIdentityKey, userId, serverWallet, walletStorage, expected, minSats) {
110
+ const args = (params?.[1] ?? {});
111
+ if (typeof args.reference !== 'string' || args.reference.length === 0) {
112
+ return undefined;
113
+ }
114
+ const storage = walletStorage;
115
+ let transactionId;
116
+ try {
117
+ const txs = await storage.findTransactions({
118
+ partial: { reference: args.reference, userId },
119
+ noRawTx: true,
45
120
  });
46
- if (capacity.deficitBytes <= 0)
47
- return { type: 'allow' };
48
- const paymentHeaders = readBrc0121Headers(input.request);
49
- if (!paymentHeaders) {
50
- return {
51
- type: 'blocked',
52
- response: this.buildChallenge(input.id, capacity.deficitBytes),
53
- };
121
+ transactionId = txs[0]?.transactionId;
122
+ }
123
+ catch {
124
+ return undefined;
125
+ }
126
+ if (transactionId == null)
127
+ return undefined;
128
+ let outputs;
129
+ try {
130
+ outputs = await storage.findOutputs({
131
+ partial: { transactionId, userId },
132
+ });
133
+ }
134
+ catch {
135
+ return undefined;
136
+ }
137
+ let expectedScriptHex;
138
+ try {
139
+ expectedScriptHex = await deriveExpectedPaymentScript(serverWallet, senderIdentityKey, expected);
140
+ }
141
+ catch {
142
+ return undefined;
143
+ }
144
+ for (const output of outputs) {
145
+ if (!output.lockingScript || output.satoshis < minSats)
146
+ continue;
147
+ const storedHex = Utils.toHex(output.lockingScript);
148
+ if (storedHex === expectedScriptHex) {
149
+ return { outputIndex: output.vout, satoshis: output.satoshis };
54
150
  }
55
- // A payment is attached. Validate and credit before allowing the retry.
56
- const quote = priceForDeficit(capacity.deficitBytes, this.deps.config.satsPerGb);
151
+ }
152
+ return undefined;
153
+ }
154
+ /**
155
+ * After the client's processAction has broadcast the self-payment tx, this
156
+ * records it in the SERVER's own wallet (internalize) with the structured
157
+ * labels that the accounts ledger reads. Fired from `res.on('finish')` —
158
+ * any failure here cannot be reported to the client, so it's logged.
159
+ */
160
+ async function autoInternalizeSelfPayment(deps, ctx) {
161
+ const storage = deps.walletStorage;
162
+ // Build a fully-expanded AtomicBEEF for the broadcast tx. The persisted
163
+ // per-tx inputBEEF uses txidOnly references (ancestors are "known to
164
+ // storage"), which validateAtomicBeef rejects. getValidBeefForTxid
165
+ // without trustSelf recurses through each input's source to produce a
166
+ // BEEF with full rawTx + merkle proofs for all ancestors — the same
167
+ // expansion signAction performs client-side.
168
+ const beef = await storage.getValidBeefForTxid(ctx.txid);
169
+ if (!beef) {
170
+ throw new Error(`could not build BEEF for txid ${ctx.txid}`);
171
+ }
172
+ const atomicBeef = beef.toBinaryAtomic(ctx.txid);
173
+ await deps.wallet.internalizeAction({
174
+ tx: atomicBeef,
175
+ outputs: [
176
+ {
177
+ paymentRemittance: {
178
+ derivationPrefix: ctx.derivationPrefix,
179
+ derivationSuffix: ctx.derivationSuffix,
180
+ senderIdentityKey: ctx.payerIdentity,
181
+ },
182
+ outputIndex: ctx.outputIndex,
183
+ protocol: 'wallet payment',
184
+ },
185
+ ],
186
+ labels: [
187
+ PAYMENT_LABEL,
188
+ payerLabel(ctx.payerIdentity),
189
+ bytesLabel(ctx.bytesCovered),
190
+ blockLabel(ctx.paidThroughBlock),
191
+ ],
192
+ description: 'wallet-server storage payment',
193
+ });
194
+ }
195
+ /**
196
+ * Express middleware. Runs between auth and dispatch. For billable methods
197
+ * when the caller is over capacity, short-circuits with 507 + quota info.
198
+ * On processAction for a valid self-payment, schedules a post-response
199
+ * auto-internalize so the payment is recorded in the server's wallet.
200
+ */
201
+ export function accountsCapacityGate(deps) {
202
+ const freeKeys = new Set([
203
+ deps.serverIdentityKey,
204
+ ...(deps.config.freeIdentityKeys ?? []),
205
+ ]);
206
+ return async (req, res, next) => {
57
207
  try {
58
- const parsed = parseBrc0121Payment(paymentHeaders, quote.satoshisRequired);
59
- if (await this.repo.paymentExists(parsed.txid)) {
60
- return {
61
- type: 'blocked',
62
- response: errorResponse(input.id, -32001, 'payment already applied'),
63
- };
64
- }
65
- const validation = await internalizePayment({
66
- wallet: this.deps.wallet,
67
- senderIdentityKey: input.identity.identityKey,
68
- parsed,
208
+ if (!deps.config.enabled)
209
+ return next();
210
+ const method = extractJsonRpcMethod(req);
211
+ if (method == null || !isBillableMethod(method))
212
+ return next();
213
+ const identityKey = req.auth?.identityKey;
214
+ if (!identityKey)
215
+ return next();
216
+ if (freeKeys.has(identityKey))
217
+ return next();
218
+ const userId = await resolveUserId(deps.walletStorage, identityKey);
219
+ // First billable call creates the user row — gets a free pass.
220
+ if (userId == null)
221
+ return next();
222
+ const storage = deps.walletStorage;
223
+ const currentBlock = await deps.currentBlock();
224
+ const [usedBytes, currentPayment] = await Promise.all([
225
+ storage.measureUsedBytes(userId),
226
+ latestActivePaymentForPayer(deps.wallet, identityKey, currentBlock),
227
+ ]);
228
+ const quote = quoteRefundedCharge({
229
+ usedBytes,
230
+ currentPayment,
231
+ currentBlock,
232
+ config: deps.config,
69
233
  });
70
- await this.repo.upsertAccount(input.identity.identityKey);
71
- await this.repo.recordPayment({
72
- identityKey: input.identity.identityKey,
73
- txid: validation.txid,
74
- bytesCovered: quote.bytesCovered,
75
- satsPaid: validation.satoshisReceived,
76
- paidThroughBlock: currentBlock + this.deps.config.durationBlocks,
234
+ if (!quote)
235
+ return next();
236
+ const nextPayment = await nextPaymentDerivation(identityKey, deps.wallet);
237
+ const params = req.body?.params ?? [];
238
+ if (method === 'createAction') {
239
+ const match = await matchCreateActionPayment(params, identityKey, deps.serverIdentityKey, deps.wallet, nextPayment, quote.chargeSats);
240
+ if (match)
241
+ return next();
242
+ }
243
+ else if (method === 'processAction') {
244
+ const match = await matchProcessActionPayment(params, identityKey, userId, deps.wallet, deps.walletStorage, nextPayment, quote.chargeSats);
245
+ if (match) {
246
+ const processArgs = params[1];
247
+ if (typeof processArgs?.txid === 'string') {
248
+ const ctx = {
249
+ txid: processArgs.txid,
250
+ outputIndex: match.outputIndex,
251
+ payerIdentity: identityKey,
252
+ derivationPrefix: nextPayment.derivationPrefix,
253
+ derivationSuffix: nextPayment.derivationSuffix,
254
+ bytesCovered: quote.bytesCovered,
255
+ paidThroughBlock: quote.paidThroughBlock,
256
+ };
257
+ res.on('finish', () => {
258
+ if (res.statusCode !== 200)
259
+ return;
260
+ autoInternalizeSelfPayment(deps, ctx).catch((err) => {
261
+ console.error('[accounts] auto-internalize failed for', ctx.txid, err);
262
+ });
263
+ });
264
+ }
265
+ return next();
266
+ }
267
+ }
268
+ const id = normalizeJsonRpcId(req.body?.id);
269
+ return res.status(507).json({
270
+ jsonrpc: '2.0',
271
+ error: {
272
+ code: ERR_INSUFFICIENT_CAPACITY,
273
+ message: 'insufficient storage capacity',
274
+ data: {
275
+ usedBytes,
276
+ baselineBytes: deps.config.baselineBytes,
277
+ paidBytes: currentPayment?.bytesCovered ?? 0,
278
+ capacityBytes: deps.config.baselineBytes + (currentPayment?.bytesCovered ?? 0),
279
+ deficitBytes: quote.bytesCovered,
280
+ satsRequired: quote.chargeSats,
281
+ fullSats: quote.fullSats,
282
+ refundSats: quote.refundSats,
283
+ paidThroughBlock: quote.paidThroughBlock,
284
+ currentBlock,
285
+ pricing: {
286
+ purchaseUnitBytes: deps.config.purchaseUnitBytes,
287
+ satsPerUnit: deps.config.satsPerUnit,
288
+ durationBlocks: deps.config.durationBlocks,
289
+ },
290
+ serverIdentityKey: deps.serverIdentityKey,
291
+ nextPayment,
292
+ },
293
+ },
294
+ id,
77
295
  });
78
- return { type: 'allow' };
79
296
  }
80
297
  catch (err) {
81
- if (err instanceof Brc0121PaymentError) {
82
- return {
83
- type: 'blocked',
84
- response: errorResponse(input.id, -32002, err.message),
85
- };
86
- }
87
- throw err;
298
+ console.error('[accounts] capacity gate error:', err);
299
+ return next();
88
300
  }
89
- }
90
- async resolveUserId(identityKey) {
91
- const result = await this.deps.walletStorage.findOrInsertUser(identityKey);
92
- return result?.user?.userId;
93
- }
94
- buildChallenge(id, deficitBytes) {
95
- const quote = priceForDeficit(deficitBytes, this.deps.config.satsPerGb);
96
- const orderID = Utils.toBase64(Random(16));
97
- const derivationPrefix = Utils.toBase64(Random(16));
98
- const body = {
99
- jsonrpc: '2.0',
100
- error: {
101
- code: -32000,
102
- message: 'payment required',
103
- data: {
104
- status: 'payment-required',
105
- satoshisRequired: quote.satoshisRequired,
106
- bytesRequested: quote.bytesCovered,
107
- gigabytesCharged: quote.gigabytesCharged,
108
- bytesPerGb: BYTES_PER_GB,
109
- derivationPrefix,
110
- orderID,
111
- },
112
- },
113
- id,
114
- };
115
- return new Response(JSON.stringify(body), {
116
- status: 402,
117
- headers: {
118
- 'content-type': 'application/json',
119
- 'x-bsv-payment-order-id': orderID,
120
- 'x-bsv-payment-derivation-prefix': derivationPrefix,
121
- 'x-bsv-payment-satoshis-required': String(quote.satoshisRequired),
122
- },
123
- });
124
- }
125
- }
126
- function errorResponse(id, code, message) {
127
- const body = {
128
- jsonrpc: '2.0',
129
- error: { code, message },
130
- id,
131
301
  };
132
- return new Response(JSON.stringify(body), {
133
- status: 402,
134
- headers: { 'content-type': 'application/json' },
135
- });
302
+ }
303
+ async function resolveUserId(storage, identityKey) {
304
+ const result = await storage.findOrInsertUser(identityKey);
305
+ return result?.user?.userId;
306
+ }
307
+ function extractJsonRpcMethod(req) {
308
+ const body = req.body;
309
+ if (typeof body !== 'object' || body === null)
310
+ return undefined;
311
+ const method = body.method;
312
+ return typeof method === 'string' ? method : undefined;
313
+ }
314
+ function normalizeJsonRpcId(id) {
315
+ if (typeof id === 'string' || typeof id === 'number')
316
+ return id;
317
+ return null;
136
318
  }
137
319
  //# sourceMappingURL=middleware.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/accounts/middleware.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,UAAU,CAAA;AAExC,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAM9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAC7C,OAAO,EACN,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,GAClB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAC1E,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;AAwBrC;;;;GAIG;AACH,MAAM,OAAO,YAAY;IAIK;IAHpB,IAAI,CAAc;IACV,QAAQ,CAAkB;IAE3C,YAA6B,IAA4B;QAA5B,SAAI,GAAJ,IAAI,CAAwB;QACxD,IAAI,CAAC,IAAI,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACvC,IAAI,CAAC,QAAQ,GAAG,IAAI,GAAG,CAAC;YACvB,IAAI,CAAC,iBAAiB;YACtB,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,gBAAgB,IAAI,EAAE,CAAC;SACvC,CAAC,CAAA;IACH,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,KAA4B;QACvC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAA;QACvD,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,MAAM,CAAC;YAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAA;QAC7D,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC;YAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAA;QAE3E,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAA;QACnE,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;YACpB,sEAAsE;YACtE,mEAAmE;YACnE,yBAAyB;YACzB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAA;QACzB,CAAC;QAED,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAA;QACnD,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QAC3D,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAClD,KAAK,CAAC,QAAQ,CAAC,WAAW,EAC1B,YAAY,CACZ,CAAA;QACD,MAAM,QAAQ,GAAG,eAAe,CAAC;YAChC,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa;YAC7C,SAAS;YACT,SAAS,EAAE,IAAI;SACf,CAAC,CAAA;QAEF,IAAI,QAAQ,CAAC,YAAY,IAAI,CAAC;YAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAA;QAExD,MAAM,cAAc,GAAG,kBAAkB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QACxD,IAAI,CAAC,cAAc,EAAE,CAAC;YACrB,OAAO;gBACN,IAAI,EAAE,SAAS;gBACf,QAAQ,EAAE,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,EAAE,QAAQ,CAAC,YAAY,CAAC;aAC9D,CAAA;QACF,CAAC;QAED,wEAAwE;QACxE,MAAM,KAAK,GAAG,eAAe,CAC5B,QAAQ,CAAC,YAAY,EACrB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAC1B,CAAA;QACD,IAAI,CAAC;YACJ,MAAM,MAAM,GAAG,mBAAmB,CAAC,cAAc,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAA;YAC1E,IAAI,MAAM,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;gBAChD,OAAO;oBACN,IAAI,EAAE,SAAS;oBACf,QAAQ,EAAE,aAAa,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,yBAAyB,CAAC;iBACpE,CAAA;YACF,CAAC;YACD,MAAM,UAAU,GAAG,MAAM,kBAAkB,CAAC;gBAC3C,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM;gBACxB,iBAAiB,EAAE,KAAK,CAAC,QAAQ,CAAC,WAAW;gBAC7C,MAAM;aACN,CAAC,CAAA;YACF,MAAM,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAA;YACzD,MAAM,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC;gBAC7B,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,WAAW;gBACvC,IAAI,EAAE,UAAU,CAAC,IAAI;gBACrB,YAAY,EAAE,KAAK,CAAC,YAAY;gBAChC,QAAQ,EAAE,UAAU,CAAC,gBAAgB;gBACrC,gBAAgB,EAAE,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc;aAChE,CAAC,CAAA;YACF,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAA;QACzB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,IAAI,GAAG,YAAY,mBAAmB,EAAE,CAAC;gBACxC,OAAO;oBACN,IAAI,EAAE,SAAS;oBACf,QAAQ,EAAE,aAAa,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC;iBACtD,CAAA;YACF,CAAC;YACD,MAAM,GAAG,CAAA;QACV,CAAC;IACF,CAAC;IAEO,KAAK,CAAC,aAAa,CAC1B,WAAwB;QAExB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAA;QAC1E,OAAO,MAAM,EAAE,IAAI,EAAE,MAAM,CAAA;IAC5B,CAAC;IAEO,cAAc,CACrB,EAA0B,EAC1B,YAAoB;QAEpB,MAAM,KAAK,GAAG,eAAe,CAAC,YAAY,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;QACvE,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAA;QAC1C,MAAM,gBAAgB,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAA;QACnD,MAAM,IAAI,GAAG;YACZ,OAAO,EAAE,KAAK;YACd,KAAK,EAAE;gBACN,IAAI,EAAE,CAAC,KAAK;gBACZ,OAAO,EAAE,kBAAkB;gBAC3B,IAAI,EAAE;oBACL,MAAM,EAAE,kBAAkB;oBAC1B,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;oBACxC,cAAc,EAAE,KAAK,CAAC,YAAY;oBAClC,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;oBACxC,UAAU,EAAE,YAAY;oBACxB,gBAAgB;oBAChB,OAAO;iBACP;aACD;YACD,EAAE;SACwB,CAAA;QAE3B,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE;YACzC,MAAM,EAAE,GAAG;YACX,OAAO,EAAE;gBACR,cAAc,EAAE,kBAAkB;gBAClC,wBAAwB,EAAE,OAAO;gBACjC,iCAAiC,EAAE,gBAAgB;gBACnD,iCAAiC,EAAE,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC;aACjE;SACD,CAAC,CAAA;IACH,CAAC;CACD;AAED,SAAS,aAAa,CACrB,EAA0B,EAC1B,IAAY,EACZ,OAAe;IAEf,MAAM,IAAI,GAAoB;QAC7B,OAAO,EAAE,KAAK;QACd,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;QACxB,EAAE;KACF,CAAA;IACD,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE;QACzC,MAAM,EAAE,GAAG;QACX,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;KAC/C,CAAC,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/accounts/middleware.ts"],"names":[],"mappings":"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"}