@1sat/wallet-server 0.0.1 → 0.0.2
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/accounts/index.d.ts +4 -7
- package/dist/accounts/index.d.ts.map +1 -1
- package/dist/accounts/index.js +3 -6
- package/dist/accounts/index.js.map +1 -1
- package/dist/accounts/middleware.d.ts +29 -30
- package/dist/accounts/middleware.d.ts.map +1 -1
- package/dist/accounts/middleware.js +303 -121
- package/dist/accounts/middleware.js.map +1 -1
- package/dist/accounts/pricing.d.ts +38 -11
- package/dist/accounts/pricing.d.ts.map +1 -1
- package/dist/accounts/pricing.js +40 -11
- package/dist/accounts/pricing.js.map +1 -1
- package/dist/accounts/queries.d.ts +42 -0
- package/dist/accounts/queries.d.ts.map +1 -0
- package/dist/accounts/queries.js +91 -0
- package/dist/accounts/queries.js.map +1 -0
- package/dist/accounts/types.d.ts +46 -29
- package/dist/accounts/types.d.ts.map +1 -1
- package/dist/client.d.ts +20 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +34 -0
- package/dist/client.js.map +1 -0
- package/dist/createWalletServer.d.ts +12 -3
- package/dist/createWalletServer.d.ts.map +1 -1
- package/dist/createWalletServer.js +84 -46
- package/dist/createWalletServer.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/topUp.d.ts +28 -0
- package/dist/topUp.d.ts.map +1 -0
- package/dist/topUp.js +67 -0
- package/dist/topUp.js.map +1 -0
- package/package.json +57 -46
- package/dist/accounts/metering.d.ts +0 -15
- package/dist/accounts/metering.d.ts.map +0 -1
- package/dist/accounts/metering.js +0 -32
- package/dist/accounts/metering.js.map +0 -1
- package/dist/accounts/migrations.d.ts +0 -18
- package/dist/accounts/migrations.d.ts.map +0 -1
- package/dist/accounts/migrations.js +0 -46
- package/dist/accounts/migrations.js.map +0 -1
- package/dist/accounts/paymentValidation.d.ts +0 -59
- package/dist/accounts/paymentValidation.d.ts.map +0 -1
- package/dist/accounts/paymentValidation.js +0 -112
- package/dist/accounts/paymentValidation.js.map +0 -1
- package/dist/accounts/repo.d.ts +0 -17
- package/dist/accounts/repo.d.ts.map +0 -1
- package/dist/accounts/repo.js +0 -94
- package/dist/accounts/repo.js.map +0 -1
package/dist/accounts/index.d.ts
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
export type {
|
|
2
|
-
export {
|
|
3
|
-
export {
|
|
4
|
-
export {
|
|
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,
|
|
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"}
|
package/dist/accounts/index.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export {
|
|
3
|
-
export {
|
|
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":"
|
|
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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
-
|
|
16
|
-
|
|
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
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
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
|
|
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,
|
|
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
|
-
|
|
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 {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
return {
|
|
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
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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
|
-
|
|
56
|
-
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
|
|
82
|
-
|
|
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
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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":"
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/accounts/middleware.ts"],"names":[],"mappings":"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"}
|