@1sat/serve 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/payment.d.ts +46 -0
- package/dist/payment.d.ts.map +1 -0
- package/dist/payment.js +149 -0
- package/dist/payment.js.map +1 -0
- package/dist/serialize.d.ts +32 -0
- package/dist/serialize.d.ts.map +1 -0
- package/dist/serialize.js +123 -0
- package/dist/serialize.js.map +1 -0
- package/dist/transport.d.ts +60 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +216 -0
- package/dist/transport.js.map +1 -0
- package/package.json +42 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { type AuthContext, type AuthenticatedHandlerOptions, type AuthHandler, BunTransport, createAuthenticatedHandler, } from './transport.js';
|
|
2
|
+
export { type OnInternalize, type PaidContext, type PaidHandler, type VerifiedPayment, withPayment, type WithPaymentOptions, } from './payment.js';
|
|
3
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,WAAW,EAChB,KAAK,2BAA2B,EAChC,KAAK,WAAW,EAChB,YAAY,EACZ,0BAA0B,GAC1B,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACN,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,WAAW,EACX,KAAK,kBAAkB,GACvB,MAAM,cAAc,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAIN,YAAY,EACZ,0BAA0B,GAC1B,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAKN,WAAW,GAEX,MAAM,cAAc,CAAA"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type InternalizeActionArgs, type WalletInterface } from '@bsv/sdk';
|
|
2
|
+
import type { AuthContext, AuthHandler } from './transport.js';
|
|
3
|
+
/** A payment verified against the server-derived BRC-29 script. */
|
|
4
|
+
export interface VerifiedPayment {
|
|
5
|
+
/** The payment transaction as AtomicBEEF bytes. */
|
|
6
|
+
tx: number[];
|
|
7
|
+
/** Index of the output that pays the server. */
|
|
8
|
+
outputIndex: number;
|
|
9
|
+
/** Satoshis on that output. */
|
|
10
|
+
satoshis: number;
|
|
11
|
+
derivationPrefix: string;
|
|
12
|
+
derivationSuffix: string;
|
|
13
|
+
/** The paying peer's identity key. */
|
|
14
|
+
senderIdentityKey: string;
|
|
15
|
+
}
|
|
16
|
+
/** The context a paid handler receives — the auth context plus the payment. */
|
|
17
|
+
export interface PaidContext extends AuthContext {
|
|
18
|
+
payment: VerifiedPayment;
|
|
19
|
+
}
|
|
20
|
+
export type PaidHandler = (ctx: PaidContext) => Promise<Response> | Response;
|
|
21
|
+
/**
|
|
22
|
+
* Decides how the verified payment is recorded. Receives the default
|
|
23
|
+
* 'wallet payment' internalize args (general balance) and returns the args to
|
|
24
|
+
* actually use — e.g. a 'basket insertion' with tags. Defaults to the wallet
|
|
25
|
+
* payment when omitted.
|
|
26
|
+
*/
|
|
27
|
+
export type OnInternalize = (payment: VerifiedPayment, defaults: InternalizeActionArgs) => InternalizeActionArgs | Promise<InternalizeActionArgs>;
|
|
28
|
+
export interface WithPaymentOptions {
|
|
29
|
+
/** Server wallet that issued the auth session; also records the payment. */
|
|
30
|
+
wallet: WalletInterface;
|
|
31
|
+
/** Flat price, or a per-request price function. */
|
|
32
|
+
price: number | ((ctx: AuthContext) => number | Promise<number>);
|
|
33
|
+
/** Optional hook to redirect the internalize (e.g. into a basket). */
|
|
34
|
+
onInternalize?: OnInternalize;
|
|
35
|
+
/** Action-level description recorded with the internalize (5..50 chars). */
|
|
36
|
+
description?: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Wraps a handler behind the BRC-105 payment flow. Wire-identical to
|
|
40
|
+
* `@bsv/payment-express-middleware`: an unpaid request gets a 402 with a
|
|
41
|
+
* derivation-prefix nonce; the paid retry is verified against the
|
|
42
|
+
* server-derived BRC-29 script and internalized (via `onInternalize`) before
|
|
43
|
+
* the wrapped handler runs. The buyer identity comes from the auth layer.
|
|
44
|
+
*/
|
|
45
|
+
export declare function withPayment(options: WithPaymentOptions, handler: PaidHandler): AuthHandler;
|
|
46
|
+
//# sourceMappingURL=payment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payment.d.ts","sourceRoot":"","sources":["../src/payment.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,KAAK,qBAAqB,EAK1B,KAAK,eAAe,EAIpB,MAAM,UAAU,CAAA;AACjB,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAM9D,mEAAmE;AACnE,MAAM,WAAW,eAAe;IAC/B,mDAAmD;IACnD,EAAE,EAAE,MAAM,EAAE,CAAA;IACZ,gDAAgD;IAChD,WAAW,EAAE,MAAM,CAAA;IACnB,+BAA+B;IAC/B,QAAQ,EAAE,MAAM,CAAA;IAChB,gBAAgB,EAAE,MAAM,CAAA;IACxB,gBAAgB,EAAE,MAAM,CAAA;IACxB,sCAAsC;IACtC,iBAAiB,EAAE,MAAM,CAAA;CACzB;AAED,+EAA+E;AAC/E,MAAM,WAAW,WAAY,SAAQ,WAAW;IAC/C,OAAO,EAAE,eAAe,CAAA;CACxB;AAED,MAAM,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAA;AAE5E;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,CAC3B,OAAO,EAAE,eAAe,EACxB,QAAQ,EAAE,qBAAqB,KAC3B,qBAAqB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAA;AAE3D,MAAM,WAAW,kBAAkB;IAClC,4EAA4E;IAC5E,MAAM,EAAE,eAAe,CAAA;IACvB,mDAAmD;IACnD,KAAK,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,WAAW,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAA;IAChE,sEAAsE;IACtE,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAA;CACpB;AAQD;;;;;;GAMG;AACH,wBAAgB,WAAW,CAC1B,OAAO,EAAE,kBAAkB,EAC3B,OAAO,EAAE,WAAW,GAClB,WAAW,CAwGb"}
|
package/dist/payment.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { P2PKH, PublicKey, Transaction, Utils, createNonce, verifyNonce, } from '@bsv/sdk';
|
|
2
|
+
/** BRC-29 protocol ID for wallet payments (matches @1sat/types). */
|
|
3
|
+
const BRC29_PROTOCOL_ID = [2, '3241645161d8'];
|
|
4
|
+
const PAYMENT_VERSION = '1.0';
|
|
5
|
+
/**
|
|
6
|
+
* Wraps a handler behind the BRC-105 payment flow. Wire-identical to
|
|
7
|
+
* `@bsv/payment-express-middleware`: an unpaid request gets a 402 with a
|
|
8
|
+
* derivation-prefix nonce; the paid retry is verified against the
|
|
9
|
+
* server-derived BRC-29 script and internalized (via `onInternalize`) before
|
|
10
|
+
* the wrapped handler runs. The buyer identity comes from the auth layer.
|
|
11
|
+
*/
|
|
12
|
+
export function withPayment(options, handler) {
|
|
13
|
+
const { wallet, onInternalize } = options;
|
|
14
|
+
return async (ctx) => {
|
|
15
|
+
if (ctx.identityKey === 'unknown') {
|
|
16
|
+
return json(401, {
|
|
17
|
+
status: 'error',
|
|
18
|
+
description: 'identity required for payment',
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
const price = typeof options.price === 'function'
|
|
22
|
+
? await options.price(ctx)
|
|
23
|
+
: options.price;
|
|
24
|
+
const rawPayment = ctx.request.headers.get('x-bsv-payment');
|
|
25
|
+
if (!rawPayment) {
|
|
26
|
+
const derivationPrefix = await createNonce(wallet);
|
|
27
|
+
return new Response(JSON.stringify({
|
|
28
|
+
status: 'error',
|
|
29
|
+
code: 'ERR_PAYMENT_REQUIRED',
|
|
30
|
+
satoshisRequired: price,
|
|
31
|
+
description: `A payment of ${price} satoshis is required.`,
|
|
32
|
+
}), {
|
|
33
|
+
status: 402,
|
|
34
|
+
headers: {
|
|
35
|
+
'content-type': 'application/json',
|
|
36
|
+
'x-bsv-payment-version': PAYMENT_VERSION,
|
|
37
|
+
'x-bsv-payment-satoshis-required': String(price),
|
|
38
|
+
'x-bsv-payment-derivation-prefix': derivationPrefix,
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
let pay;
|
|
43
|
+
try {
|
|
44
|
+
pay = JSON.parse(rawPayment);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return json(400, {
|
|
48
|
+
status: 'error',
|
|
49
|
+
description: 'malformed x-bsv-payment header',
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
let validNonce = false;
|
|
53
|
+
try {
|
|
54
|
+
validNonce = await verifyNonce(pay.derivationPrefix, wallet);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
validNonce = false;
|
|
58
|
+
}
|
|
59
|
+
if (!validNonce) {
|
|
60
|
+
return json(400, {
|
|
61
|
+
status: 'error',
|
|
62
|
+
code: 'ERR_INVALID_DERIVATION_PREFIX',
|
|
63
|
+
description: 'derivation prefix is not a nonce we issued',
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
let verified;
|
|
67
|
+
try {
|
|
68
|
+
verified = await verifyPayment(wallet, ctx.identityKey, pay, price);
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
return json(400, {
|
|
72
|
+
status: 'error',
|
|
73
|
+
code: 'ERR_PAYMENT_INVALID',
|
|
74
|
+
description: err instanceof Error ? err.message : String(err),
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
const defaults = {
|
|
78
|
+
tx: verified.tx,
|
|
79
|
+
outputs: [
|
|
80
|
+
{
|
|
81
|
+
outputIndex: verified.outputIndex,
|
|
82
|
+
protocol: 'wallet payment',
|
|
83
|
+
paymentRemittance: {
|
|
84
|
+
derivationPrefix: verified.derivationPrefix,
|
|
85
|
+
derivationSuffix: verified.derivationSuffix,
|
|
86
|
+
senderIdentityKey: verified.senderIdentityKey,
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
description: (options.description ?? 'payment for request').slice(0, 50),
|
|
91
|
+
};
|
|
92
|
+
try {
|
|
93
|
+
await wallet.internalizeAction(onInternalize ? await onInternalize(verified, defaults) : defaults);
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
return json(400, {
|
|
97
|
+
status: 'error',
|
|
98
|
+
code: 'ERR_PAYMENT_FAILED',
|
|
99
|
+
description: err instanceof Error ? err.message : String(err),
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
const response = await handler({ ...ctx, payment: verified });
|
|
103
|
+
const buf = await response.arrayBuffer();
|
|
104
|
+
const headers = new Headers(response.headers);
|
|
105
|
+
headers.set('x-bsv-payment-satoshis-paid', String(verified.satoshis));
|
|
106
|
+
return new Response(buf, { status: response.status, headers });
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Verifies the paid output: re-derives the BRC-29 P2PKH script from the buyer
|
|
111
|
+
* key + derivation and confirms an output pays it for at least `price`. This
|
|
112
|
+
* is the check `internalizeAction` performs for 'wallet payment' but skips for
|
|
113
|
+
* 'basket insertion', so we do it ourselves.
|
|
114
|
+
*/
|
|
115
|
+
async function verifyPayment(wallet, senderIdentityKey, pay, price) {
|
|
116
|
+
const { publicKey } = await wallet.getPublicKey({
|
|
117
|
+
protocolID: BRC29_PROTOCOL_ID,
|
|
118
|
+
keyID: `${pay.derivationPrefix} ${pay.derivationSuffix}`,
|
|
119
|
+
counterparty: senderIdentityKey,
|
|
120
|
+
forSelf: true,
|
|
121
|
+
});
|
|
122
|
+
const expectedScript = new P2PKH()
|
|
123
|
+
.lock(PublicKey.fromString(publicKey).toAddress())
|
|
124
|
+
.toHex();
|
|
125
|
+
const txBytes = Utils.toArray(pay.transaction, 'base64');
|
|
126
|
+
const tx = Transaction.fromAtomicBEEF(txBytes);
|
|
127
|
+
for (let i = 0; i < tx.outputs.length; i++) {
|
|
128
|
+
const out = tx.outputs[i];
|
|
129
|
+
if (out?.lockingScript.toHex() === expectedScript &&
|
|
130
|
+
(out.satoshis ?? 0) >= price) {
|
|
131
|
+
return {
|
|
132
|
+
tx: txBytes,
|
|
133
|
+
outputIndex: i,
|
|
134
|
+
satoshis: out.satoshis ?? 0,
|
|
135
|
+
derivationPrefix: pay.derivationPrefix,
|
|
136
|
+
derivationSuffix: pay.derivationSuffix,
|
|
137
|
+
senderIdentityKey,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
throw new Error('no output pays the derived script for the required amount');
|
|
142
|
+
}
|
|
143
|
+
function json(status, body) {
|
|
144
|
+
return new Response(JSON.stringify(body), {
|
|
145
|
+
status,
|
|
146
|
+
headers: { 'content-type': 'application/json' },
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=payment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payment.js","sourceRoot":"","sources":["../src/payment.ts"],"names":[],"mappings":"AAAA,OAAO,EAGN,KAAK,EACL,SAAS,EACT,WAAW,EACX,KAAK,EAGL,WAAW,EACX,WAAW,GACX,MAAM,UAAU,CAAA;AAGjB,oEAAoE;AACpE,MAAM,iBAAiB,GAAmB,CAAC,CAAC,EAAE,cAAc,CAAC,CAAA;AAC7D,MAAM,eAAe,GAAG,KAAK,CAAA;AAmD7B;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAC1B,OAA2B,EAC3B,OAAoB;IAEpB,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,CAAA;IACzC,OAAO,KAAK,EAAE,GAAgB,EAAqB,EAAE;QACpD,IAAI,GAAG,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;YACnC,OAAO,IAAI,CAAC,GAAG,EAAE;gBAChB,MAAM,EAAE,OAAO;gBACf,WAAW,EAAE,+BAA+B;aAC5C,CAAC,CAAA;QACH,CAAC;QACD,MAAM,KAAK,GACV,OAAO,OAAO,CAAC,KAAK,KAAK,UAAU;YAClC,CAAC,CAAC,MAAM,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC;YAC1B,CAAC,CAAC,OAAO,CAAC,KAAK,CAAA;QAEjB,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAA;QAC3D,IAAI,CAAC,UAAU,EAAE,CAAC;YACjB,MAAM,gBAAgB,GAAG,MAAM,WAAW,CAAC,MAAM,CAAC,CAAA;YAClD,OAAO,IAAI,QAAQ,CAClB,IAAI,CAAC,SAAS,CAAC;gBACd,MAAM,EAAE,OAAO;gBACf,IAAI,EAAE,sBAAsB;gBAC5B,gBAAgB,EAAE,KAAK;gBACvB,WAAW,EAAE,gBAAgB,KAAK,wBAAwB;aAC1D,CAAC,EACF;gBACC,MAAM,EAAE,GAAG;gBACX,OAAO,EAAE;oBACR,cAAc,EAAE,kBAAkB;oBAClC,uBAAuB,EAAE,eAAe;oBACxC,iCAAiC,EAAE,MAAM,CAAC,KAAK,CAAC;oBAChD,iCAAiC,EAAE,gBAAgB;iBACnD;aACD,CACD,CAAA;QACF,CAAC;QAED,IAAI,GAAkB,CAAA;QACtB,IAAI,CAAC;YACJ,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAkB,CAAA;QAC9C,CAAC;QAAC,MAAM,CAAC;YACR,OAAO,IAAI,CAAC,GAAG,EAAE;gBAChB,MAAM,EAAE,OAAO;gBACf,WAAW,EAAE,gCAAgC;aAC7C,CAAC,CAAA;QACH,CAAC;QAED,IAAI,UAAU,GAAG,KAAK,CAAA;QACtB,IAAI,CAAC;YACJ,UAAU,GAAG,MAAM,WAAW,CAAC,GAAG,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAA;QAC7D,CAAC;QAAC,MAAM,CAAC;YACR,UAAU,GAAG,KAAK,CAAA;QACnB,CAAC;QACD,IAAI,CAAC,UAAU,EAAE,CAAC;YACjB,OAAO,IAAI,CAAC,GAAG,EAAE;gBAChB,MAAM,EAAE,OAAO;gBACf,IAAI,EAAE,+BAA+B;gBACrC,WAAW,EAAE,4CAA4C;aACzD,CAAC,CAAA;QACH,CAAC;QAED,IAAI,QAAyB,CAAA;QAC7B,IAAI,CAAC;YACJ,QAAQ,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE,GAAG,CAAC,WAAW,EAAE,GAAG,EAAE,KAAK,CAAC,CAAA;QACpE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,OAAO,IAAI,CAAC,GAAG,EAAE;gBAChB,MAAM,EAAE,OAAO;gBACf,IAAI,EAAE,qBAAqB;gBAC3B,WAAW,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;aAC7D,CAAC,CAAA;QACH,CAAC;QAED,MAAM,QAAQ,GAA0B;YACvC,EAAE,EAAE,QAAQ,CAAC,EAAgB;YAC7B,OAAO,EAAE;gBACR;oBACC,WAAW,EAAE,QAAQ,CAAC,WAAW;oBACjC,QAAQ,EAAE,gBAAgB;oBAC1B,iBAAiB,EAAE;wBAClB,gBAAgB,EAAE,QAAQ,CAAC,gBAAgB;wBAC3C,gBAAgB,EAAE,QAAQ,CAAC,gBAAgB;wBAC3C,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB;qBAC7C;iBACD;aACD;YACD,WAAW,EAAE,CAAC,OAAO,CAAC,WAAW,IAAI,qBAAqB,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;SACxE,CAAA;QACD,IAAI,CAAC;YACJ,MAAM,MAAM,CAAC,iBAAiB,CAC7B,aAAa,CAAC,CAAC,CAAC,MAAM,aAAa,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAClE,CAAA;QACF,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,OAAO,IAAI,CAAC,GAAG,EAAE;gBAChB,MAAM,EAAE,OAAO;gBACf,IAAI,EAAE,oBAAoB;gBAC1B,WAAW,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;aAC7D,CAAC,CAAA;QACH,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,EAAE,GAAG,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAA;QAC7D,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAA;QACxC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAC7C,OAAO,CAAC,GAAG,CAAC,6BAA6B,EAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAA;QACrE,OAAO,IAAI,QAAQ,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAA;IAC/D,CAAC,CAAA;AACF,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,aAAa,CAC3B,MAAuB,EACvB,iBAAyB,EACzB,GAAkB,EAClB,KAAa;IAEb,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC;QAC/C,UAAU,EAAE,iBAAiB;QAC7B,KAAK,EAAE,GAAG,GAAG,CAAC,gBAAgB,IAAI,GAAG,CAAC,gBAAgB,EAAE;QACxD,YAAY,EAAE,iBAAiB;QAC/B,OAAO,EAAE,IAAI;KACb,CAAC,CAAA;IACF,MAAM,cAAc,GAAG,IAAI,KAAK,EAAE;SAChC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,SAAS,EAAE,CAAC;SACjD,KAAK,EAAE,CAAA;IAET,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAA;IACxD,MAAM,EAAE,GAAG,WAAW,CAAC,cAAc,CAAC,OAAO,CAAC,CAAA;IAC9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5C,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;QACzB,IACC,GAAG,EAAE,aAAa,CAAC,KAAK,EAAE,KAAK,cAAc;YAC7C,CAAC,GAAG,CAAC,QAAQ,IAAI,CAAC,CAAC,IAAI,KAAK,EAC3B,CAAC;YACF,OAAO;gBACN,EAAE,EAAE,OAAO;gBACX,WAAW,EAAE,CAAC;gBACd,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,CAAC;gBAC3B,gBAAgB,EAAE,GAAG,CAAC,gBAAgB;gBACtC,gBAAgB,EAAE,GAAG,CAAC,gBAAgB;gBACtC,iBAAiB;aACjB,CAAA;QACF,CAAC;IACF,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAA;AAC7E,CAAC;AAED,SAAS,IAAI,CAAC,MAAc,EAAE,IAAa;IAC1C,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE;QACzC,MAAM;QACN,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;KAC/C,CAAC,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical byte serializations for BRC-104 general (authenticated) HTTP
|
|
3
|
+
* messages. These MUST match the client (`@bsv/sdk` AuthFetch /
|
|
4
|
+
* SimplifiedFetchTransport) byte-for-byte, or signature verification fails.
|
|
5
|
+
*
|
|
6
|
+
* Ported from the BSV `ExpressTransport` server, adapted to the web
|
|
7
|
+
* `Request`/`Response` model: the request body is the raw bytes received (not
|
|
8
|
+
* a parsed-then-restringified form), which is exactly what the client signed.
|
|
9
|
+
*/
|
|
10
|
+
/** A general HTTP response decoded from a signed message payload. */
|
|
11
|
+
export interface DecodedResponse {
|
|
12
|
+
requestId: string;
|
|
13
|
+
status: number;
|
|
14
|
+
headers: Record<string, string>;
|
|
15
|
+
body?: number[];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Reproduces the signed payload for an incoming general request: request
|
|
19
|
+
* nonce, method, pathname, search, the signed subset of headers (sorted), and
|
|
20
|
+
* the body. `bodyBytes` is the raw request body, or null when there is none.
|
|
21
|
+
*/
|
|
22
|
+
export declare function buildRequestPayload(request: Request, bodyBytes: number[] | null): number[];
|
|
23
|
+
/**
|
|
24
|
+
* Builds the payload the server signs for a general response: request id,
|
|
25
|
+
* status, the signed subset of response headers (sorted), and the body.
|
|
26
|
+
*/
|
|
27
|
+
export declare function buildResponsePayload(requestId: string, status: number, headers: Record<string, string>, body: number[]): number[];
|
|
28
|
+
/** Decodes a signed general-response payload back into an HTTP response. */
|
|
29
|
+
export declare function decodeResponse(payload: number[]): DecodedResponse;
|
|
30
|
+
/** The request id (base64 of the first 32 payload bytes) of a general message. */
|
|
31
|
+
export declare function requestIdOf(payload: number[]): string;
|
|
32
|
+
//# sourceMappingURL=serialize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serialize.d.ts","sourceRoot":"","sources":["../src/serialize.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AAEH,qEAAqE;AACrE,MAAM,WAAW,eAAe;IAC/B,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;CACf;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAClC,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,GACxB,MAAM,EAAE,CA6BV;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,IAAI,EAAE,MAAM,EAAE,GACZ,MAAM,EAAE,CAgCV;AAED,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,eAAe,CAmBjE;AAED,kFAAkF;AAClF,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,CAErD"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { Utils } from '@bsv/sdk';
|
|
2
|
+
/**
|
|
3
|
+
* Reproduces the signed payload for an incoming general request: request
|
|
4
|
+
* nonce, method, pathname, search, the signed subset of headers (sorted), and
|
|
5
|
+
* the body. `bodyBytes` is the raw request body, or null when there is none.
|
|
6
|
+
*/
|
|
7
|
+
export function buildRequestPayload(request, bodyBytes) {
|
|
8
|
+
const url = new URL(request.url);
|
|
9
|
+
const writer = new Utils.Writer();
|
|
10
|
+
const requestNonce = request.headers.get('x-bsv-auth-request-id');
|
|
11
|
+
writer.write(requestNonce ? Utils.toArray(requestNonce, 'base64') : []);
|
|
12
|
+
writer.writeVarIntNum(request.method.length);
|
|
13
|
+
writer.write(Utils.toArray(request.method));
|
|
14
|
+
if (url.pathname.length > 0) {
|
|
15
|
+
const pathname = Utils.toArray(url.pathname);
|
|
16
|
+
writer.writeVarIntNum(pathname.length);
|
|
17
|
+
writer.write(pathname);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
writer.writeVarIntNum(-1);
|
|
21
|
+
}
|
|
22
|
+
if (url.search.length > 0) {
|
|
23
|
+
const search = Utils.toArray(url.search);
|
|
24
|
+
writer.writeVarIntNum(search.length);
|
|
25
|
+
writer.write(search);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
writer.writeVarIntNum(-1);
|
|
29
|
+
}
|
|
30
|
+
writeSignedHeaders(writer, request.headers);
|
|
31
|
+
writeBody(writer, bodyBytes);
|
|
32
|
+
return writer.toArray();
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Builds the payload the server signs for a general response: request id,
|
|
36
|
+
* status, the signed subset of response headers (sorted), and the body.
|
|
37
|
+
*/
|
|
38
|
+
export function buildResponsePayload(requestId, status, headers, body) {
|
|
39
|
+
const writer = new Utils.Writer();
|
|
40
|
+
writer.write(Utils.toArray(requestId, 'base64'));
|
|
41
|
+
writer.writeVarIntNum(status);
|
|
42
|
+
const included = [];
|
|
43
|
+
for (const [k, v] of Object.entries(headers)) {
|
|
44
|
+
const key = k.toLowerCase();
|
|
45
|
+
if ((key.startsWith('x-bsv-') || key === 'authorization') &&
|
|
46
|
+
!key.startsWith('x-bsv-auth')) {
|
|
47
|
+
included.push([key, v]);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
included.sort(([a], [b]) => a.localeCompare(b));
|
|
51
|
+
writer.writeVarIntNum(included.length);
|
|
52
|
+
for (const [key, value] of included) {
|
|
53
|
+
const keyBytes = Utils.toArray(key, 'utf8');
|
|
54
|
+
writer.writeVarIntNum(keyBytes.length);
|
|
55
|
+
writer.write(keyBytes);
|
|
56
|
+
const valueBytes = Utils.toArray(value, 'utf8');
|
|
57
|
+
writer.writeVarIntNum(valueBytes.length);
|
|
58
|
+
writer.write(valueBytes);
|
|
59
|
+
}
|
|
60
|
+
// Response bodies always carry a real length prefix (0 when empty) — unlike
|
|
61
|
+
// request bodies, which use the -1 "absent" sentinel.
|
|
62
|
+
writer.writeVarIntNum(body.length);
|
|
63
|
+
if (body.length > 0)
|
|
64
|
+
writer.write(body);
|
|
65
|
+
return writer.toArray();
|
|
66
|
+
}
|
|
67
|
+
/** Decodes a signed general-response payload back into an HTTP response. */
|
|
68
|
+
export function decodeResponse(payload) {
|
|
69
|
+
const reader = new Utils.Reader(payload);
|
|
70
|
+
const requestId = Utils.toBase64(reader.read(32));
|
|
71
|
+
const status = reader.readVarIntNum();
|
|
72
|
+
const headers = {};
|
|
73
|
+
const nHeaders = reader.readVarIntNum();
|
|
74
|
+
for (let i = 0; i < nHeaders; i++) {
|
|
75
|
+
const keyLen = reader.readVarIntNum();
|
|
76
|
+
const key = Utils.toUTF8(reader.read(keyLen));
|
|
77
|
+
const valueLen = reader.readVarIntNum();
|
|
78
|
+
headers[key] = Utils.toUTF8(reader.read(valueLen));
|
|
79
|
+
}
|
|
80
|
+
let body;
|
|
81
|
+
const bodyLen = reader.readVarIntNum();
|
|
82
|
+
if (bodyLen > 0)
|
|
83
|
+
body = reader.read(bodyLen);
|
|
84
|
+
return { requestId, status, headers, body };
|
|
85
|
+
}
|
|
86
|
+
/** The request id (base64 of the first 32 payload bytes) of a general message. */
|
|
87
|
+
export function requestIdOf(payload) {
|
|
88
|
+
return Utils.toBase64(new Utils.Reader(payload).read(32));
|
|
89
|
+
}
|
|
90
|
+
function writeSignedHeaders(writer, headers) {
|
|
91
|
+
const included = [];
|
|
92
|
+
for (const [k, v] of headers.entries()) {
|
|
93
|
+
const key = k.toLowerCase();
|
|
94
|
+
const value = key === 'content-type' ? v.split(';')[0].trim() : v;
|
|
95
|
+
if ((key.startsWith('x-bsv-') ||
|
|
96
|
+
key === 'content-type' ||
|
|
97
|
+
key === 'authorization') &&
|
|
98
|
+
!key.startsWith('x-bsv-auth')) {
|
|
99
|
+
included.push([key, value]);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
included.sort(([a], [b]) => a.localeCompare(b));
|
|
103
|
+
writer.writeVarIntNum(included.length);
|
|
104
|
+
for (const [key, value] of included) {
|
|
105
|
+
const keyBytes = Utils.toArray(key, 'utf8');
|
|
106
|
+
writer.writeVarIntNum(keyBytes.length);
|
|
107
|
+
writer.write(keyBytes);
|
|
108
|
+
const valueBytes = Utils.toArray(value, 'utf8');
|
|
109
|
+
writer.writeVarIntNum(valueBytes.length);
|
|
110
|
+
writer.write(valueBytes);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/** A present body writes its length then bytes; an absent body writes -1. */
|
|
114
|
+
function writeBody(writer, bodyBytes) {
|
|
115
|
+
if (bodyBytes && bodyBytes.length > 0) {
|
|
116
|
+
writer.writeVarIntNum(bodyBytes.length);
|
|
117
|
+
writer.write(bodyBytes);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
writer.writeVarIntNum(-1);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=serialize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serialize.js","sourceRoot":"","sources":["../src/serialize.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { type AuthMessage, Peer, type RequestedCertificateSet, SessionManager, type Transport, type WalletInterface } from '@bsv/sdk';
|
|
2
|
+
/** The authenticated context handed to a route handler. */
|
|
3
|
+
export interface AuthContext {
|
|
4
|
+
/** The raw incoming request. */
|
|
5
|
+
request: Request;
|
|
6
|
+
/** Parsed URL of the request. */
|
|
7
|
+
url: URL;
|
|
8
|
+
/** The peer's BRC-103 identity key, or 'unknown' when unauthenticated. */
|
|
9
|
+
identityKey: string;
|
|
10
|
+
}
|
|
11
|
+
/** A route handler: receives the authenticated request, returns a response. */
|
|
12
|
+
export type AuthHandler = (ctx: AuthContext) => Promise<Response> | Response;
|
|
13
|
+
export interface AuthenticatedHandlerOptions {
|
|
14
|
+
/** Server wallet used to run the BRC-103/104 handshake and sign responses. */
|
|
15
|
+
wallet: WalletInterface;
|
|
16
|
+
/** The route handler invoked once a request is authenticated. */
|
|
17
|
+
handler: AuthHandler;
|
|
18
|
+
/**
|
|
19
|
+
* When true, requests with no auth headers are passed through with
|
|
20
|
+
* `identityKey = 'unknown'` (unsigned). When false (default), they get 401.
|
|
21
|
+
*/
|
|
22
|
+
allowUnauthenticated?: boolean;
|
|
23
|
+
/** Certificates to request from the peer during the handshake. */
|
|
24
|
+
certificatesToRequest?: RequestedCertificateSet;
|
|
25
|
+
/** Reuse an existing session manager (defaults to a fresh one). */
|
|
26
|
+
sessionManager?: SessionManager;
|
|
27
|
+
}
|
|
28
|
+
declare const AUTH_HEADER_KEYS: readonly ["x-bsv-auth-version", "x-bsv-auth-identity-key", "x-bsv-auth-nonce", "x-bsv-auth-your-nonce", "x-bsv-auth-signature", "x-bsv-auth-request-id"];
|
|
29
|
+
/**
|
|
30
|
+
* A BRC-103/104 mutual-auth `Transport` bound to Bun's `Request`/`Response`.
|
|
31
|
+
*
|
|
32
|
+
* Where the Express transport hijacks a mutable `res` and gates on `next()`,
|
|
33
|
+
* this models each request as a promise: it feeds the incoming message to the
|
|
34
|
+
* `Peer`, runs the route handler once the peer confirms the identity, and
|
|
35
|
+
* resolves the request's promise when the peer emits the signed reply through
|
|
36
|
+
* `send`. Wire-identical to the Express middleware.
|
|
37
|
+
*/
|
|
38
|
+
export declare class BunTransport implements Transport {
|
|
39
|
+
private readonly handler;
|
|
40
|
+
private readonly allowUnauthenticated;
|
|
41
|
+
private peer?;
|
|
42
|
+
private messageCallback?;
|
|
43
|
+
private readonly pendingNonGeneral;
|
|
44
|
+
private readonly pendingGeneral;
|
|
45
|
+
constructor(handler: AuthHandler, allowUnauthenticated: boolean);
|
|
46
|
+
setPeer(peer: Peer): void;
|
|
47
|
+
onData(callback: (message: AuthMessage) => Promise<void>): Promise<void>;
|
|
48
|
+
/** Delivers a signed message from the peer back to its pending request. */
|
|
49
|
+
send(message: AuthMessage): Promise<void>;
|
|
50
|
+
/** Handles one HTTP request end to end, returning the (signed) response. */
|
|
51
|
+
handleRequest(request: Request): Promise<Response>;
|
|
52
|
+
private handleHandshake;
|
|
53
|
+
private handleGeneral;
|
|
54
|
+
/** Runs the route handler and signs its response back to the peer. */
|
|
55
|
+
private runHandler;
|
|
56
|
+
}
|
|
57
|
+
/** Builds the Bun `fetch` handler that authenticates every request. */
|
|
58
|
+
export declare function createAuthenticatedHandler(options: AuthenticatedHandlerOptions): (request: Request) => Promise<Response>;
|
|
59
|
+
export { AUTH_HEADER_KEYS };
|
|
60
|
+
//# sourceMappingURL=transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,WAAW,EAChB,IAAI,EACJ,KAAK,uBAAuB,EAC5B,cAAc,EACd,KAAK,SAAS,EAEd,KAAK,eAAe,EACpB,MAAM,UAAU,CAAA;AAQjB,2DAA2D;AAC3D,MAAM,WAAW,WAAW;IAC3B,gCAAgC;IAChC,OAAO,EAAE,OAAO,CAAA;IAChB,iCAAiC;IACjC,GAAG,EAAE,GAAG,CAAA;IACR,0EAA0E;IAC1E,WAAW,EAAE,MAAM,CAAA;CACnB;AAED,+EAA+E;AAC/E,MAAM,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAA;AAE5E,MAAM,WAAW,2BAA2B;IAC3C,8EAA8E;IAC9E,MAAM,EAAE,eAAe,CAAA;IACvB,iEAAiE;IACjE,OAAO,EAAE,WAAW,CAAA;IACpB;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAC9B,kEAAkE;IAClE,qBAAqB,CAAC,EAAE,uBAAuB,CAAA;IAC/C,mEAAmE;IACnE,cAAc,CAAC,EAAE,cAAc,CAAA;CAC/B;AAwBD,QAAA,MAAM,gBAAgB,0JAOZ,CAAA;AAEV;;;;;;;;GAQG;AACH,qBAAa,YAAa,YAAW,SAAS;IAO5C,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,oBAAoB;IAPtC,OAAO,CAAC,IAAI,CAAC,CAAM;IACnB,OAAO,CAAC,eAAe,CAAC,CAAyC;IACjE,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAwC;IAC1E,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAoC;gBAGjD,OAAO,EAAE,WAAW,EACpB,oBAAoB,EAAE,OAAO;IAG/C,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAInB,MAAM,CACX,QAAQ,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,GAC/C,OAAO,CAAC,IAAI,CAAC;IAIhB,2EAA2E;IACrE,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IA+C/C,4EAA4E;IACtE,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;YA2B1C,eAAe;YAcf,aAAa;IA4C3B,sEAAsE;YACxD,UAAU;CA2BxB;AAED,uEAAuE;AACvE,wBAAgB,0BAA0B,CACzC,OAAO,EAAE,2BAA2B,GAClC,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAezC;AAuBD,OAAO,EAAE,gBAAgB,EAAE,CAAA"}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { Peer, SessionManager, Utils, } from '@bsv/sdk';
|
|
2
|
+
import { buildRequestPayload, buildResponsePayload, decodeResponse, requestIdOf, } from './serialize.js';
|
|
3
|
+
function defer() {
|
|
4
|
+
let resolve;
|
|
5
|
+
let reject;
|
|
6
|
+
const promise = new Promise((res, rej) => {
|
|
7
|
+
resolve = res;
|
|
8
|
+
reject = rej;
|
|
9
|
+
});
|
|
10
|
+
return { promise, resolve, reject };
|
|
11
|
+
}
|
|
12
|
+
const AUTH_HEADER_KEYS = [
|
|
13
|
+
'x-bsv-auth-version',
|
|
14
|
+
'x-bsv-auth-identity-key',
|
|
15
|
+
'x-bsv-auth-nonce',
|
|
16
|
+
'x-bsv-auth-your-nonce',
|
|
17
|
+
'x-bsv-auth-signature',
|
|
18
|
+
'x-bsv-auth-request-id',
|
|
19
|
+
];
|
|
20
|
+
/**
|
|
21
|
+
* A BRC-103/104 mutual-auth `Transport` bound to Bun's `Request`/`Response`.
|
|
22
|
+
*
|
|
23
|
+
* Where the Express transport hijacks a mutable `res` and gates on `next()`,
|
|
24
|
+
* this models each request as a promise: it feeds the incoming message to the
|
|
25
|
+
* `Peer`, runs the route handler once the peer confirms the identity, and
|
|
26
|
+
* resolves the request's promise when the peer emits the signed reply through
|
|
27
|
+
* `send`. Wire-identical to the Express middleware.
|
|
28
|
+
*/
|
|
29
|
+
export class BunTransport {
|
|
30
|
+
handler;
|
|
31
|
+
allowUnauthenticated;
|
|
32
|
+
peer;
|
|
33
|
+
messageCallback;
|
|
34
|
+
pendingNonGeneral = new Map();
|
|
35
|
+
pendingGeneral = new Map();
|
|
36
|
+
constructor(handler, allowUnauthenticated) {
|
|
37
|
+
this.handler = handler;
|
|
38
|
+
this.allowUnauthenticated = allowUnauthenticated;
|
|
39
|
+
}
|
|
40
|
+
setPeer(peer) {
|
|
41
|
+
this.peer = peer;
|
|
42
|
+
}
|
|
43
|
+
async onData(callback) {
|
|
44
|
+
this.messageCallback = callback;
|
|
45
|
+
}
|
|
46
|
+
/** Delivers a signed message from the peer back to its pending request. */
|
|
47
|
+
async send(message) {
|
|
48
|
+
if (message.messageType !== 'general') {
|
|
49
|
+
const deferred = this.pendingNonGeneral.get(message.yourNonce ?? '');
|
|
50
|
+
if (!deferred)
|
|
51
|
+
throw new Error('No open handshake handle for this peer');
|
|
52
|
+
this.pendingNonGeneral.delete(message.yourNonce ?? '');
|
|
53
|
+
const headers = {
|
|
54
|
+
'content-type': 'application/json',
|
|
55
|
+
'x-bsv-auth-version': message.version,
|
|
56
|
+
'x-bsv-auth-message-type': message.messageType,
|
|
57
|
+
'x-bsv-auth-identity-key': message.identityKey,
|
|
58
|
+
'x-bsv-auth-nonce': message.nonce ?? '',
|
|
59
|
+
'x-bsv-auth-your-nonce': message.yourNonce ?? '',
|
|
60
|
+
'x-bsv-auth-signature': Utils.toHex(message.signature ?? []),
|
|
61
|
+
};
|
|
62
|
+
if (message.requestedCertificates) {
|
|
63
|
+
headers['x-bsv-auth-requested-certificates'] = JSON.stringify(message.requestedCertificates);
|
|
64
|
+
}
|
|
65
|
+
deferred.resolve(new Response(JSON.stringify(message), { status: 200, headers }));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (!message.payload)
|
|
69
|
+
throw new Error('general message has no payload');
|
|
70
|
+
const requestId = requestIdOf(message.payload);
|
|
71
|
+
const pending = this.pendingGeneral.get(requestId);
|
|
72
|
+
if (!pending)
|
|
73
|
+
throw new Error('No open response handle for this requestId');
|
|
74
|
+
this.pendingGeneral.delete(requestId);
|
|
75
|
+
const decoded = decodeResponse(message.payload);
|
|
76
|
+
const headers = { ...pending.passthrough };
|
|
77
|
+
for (const [k, v] of Object.entries(decoded.headers))
|
|
78
|
+
headers[k] = v;
|
|
79
|
+
headers['x-bsv-auth-version'] = message.version;
|
|
80
|
+
headers['x-bsv-auth-identity-key'] = message.identityKey;
|
|
81
|
+
headers['x-bsv-auth-nonce'] = message.nonce ?? '';
|
|
82
|
+
headers['x-bsv-auth-your-nonce'] = message.yourNonce ?? '';
|
|
83
|
+
headers['x-bsv-auth-signature'] = Utils.toHex(message.signature ?? []);
|
|
84
|
+
headers['x-bsv-auth-request-id'] = requestId;
|
|
85
|
+
const body = decoded.body ? new Uint8Array(decoded.body) : undefined;
|
|
86
|
+
pending.deferred.resolve(new Response(body, { status: decoded.status, headers }));
|
|
87
|
+
}
|
|
88
|
+
/** Handles one HTTP request end to end, returning the (signed) response. */
|
|
89
|
+
async handleRequest(request) {
|
|
90
|
+
if (!this.peer || !this.messageCallback) {
|
|
91
|
+
return json(500, {
|
|
92
|
+
status: 'error',
|
|
93
|
+
description: 'auth transport not ready',
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
const url = new URL(request.url);
|
|
97
|
+
if (url.pathname === '/.well-known/auth') {
|
|
98
|
+
return this.handleHandshake(request);
|
|
99
|
+
}
|
|
100
|
+
if (request.headers.get('x-bsv-auth-request-id')) {
|
|
101
|
+
return this.handleGeneral(request, url);
|
|
102
|
+
}
|
|
103
|
+
if (this.allowUnauthenticated) {
|
|
104
|
+
return Promise.resolve(this.handler({ request, url, identityKey: 'unknown' }));
|
|
105
|
+
}
|
|
106
|
+
return json(401, {
|
|
107
|
+
status: 'error',
|
|
108
|
+
code: 'UNAUTHORIZED',
|
|
109
|
+
message: 'Mutual-authentication failed!',
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
async handleHandshake(request) {
|
|
113
|
+
const message = (await request.json());
|
|
114
|
+
const key = message.initialNonce ?? '';
|
|
115
|
+
const deferred = defer();
|
|
116
|
+
this.pendingNonGeneral.set(key, deferred);
|
|
117
|
+
try {
|
|
118
|
+
await this.messageCallback?.(message);
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
this.pendingNonGeneral.delete(key);
|
|
122
|
+
return authError(err);
|
|
123
|
+
}
|
|
124
|
+
return deferred.promise;
|
|
125
|
+
}
|
|
126
|
+
async handleGeneral(request, url) {
|
|
127
|
+
// Read a clone for the signed payload so the handler can still read the body.
|
|
128
|
+
const rawBody = await request.clone().arrayBuffer();
|
|
129
|
+
const bodyBytes = rawBody.byteLength > 0 ? [...new Uint8Array(rawBody)] : null;
|
|
130
|
+
const requestId = request.headers.get('x-bsv-auth-request-id');
|
|
131
|
+
const claimedIdentity = request.headers.get('x-bsv-auth-identity-key') ?? '';
|
|
132
|
+
const message = {
|
|
133
|
+
messageType: 'general',
|
|
134
|
+
version: request.headers.get('x-bsv-auth-version') ?? '',
|
|
135
|
+
identityKey: claimedIdentity,
|
|
136
|
+
nonce: request.headers.get('x-bsv-auth-nonce') ?? undefined,
|
|
137
|
+
yourNonce: request.headers.get('x-bsv-auth-your-nonce') ?? undefined,
|
|
138
|
+
payload: buildRequestPayload(request, bodyBytes),
|
|
139
|
+
signature: hexToBytes(request.headers.get('x-bsv-auth-signature')),
|
|
140
|
+
};
|
|
141
|
+
const deferred = defer();
|
|
142
|
+
this.pendingGeneral.set(requestId, { deferred, passthrough: {} });
|
|
143
|
+
const peer = this.peer;
|
|
144
|
+
const listenerId = peer.listenForGeneralMessages((senderPublicKey, payload) => {
|
|
145
|
+
if (senderPublicKey !== claimedIdentity)
|
|
146
|
+
return;
|
|
147
|
+
if (requestIdOf(payload) !== requestId)
|
|
148
|
+
return;
|
|
149
|
+
peer.stopListeningForGeneralMessages(listenerId);
|
|
150
|
+
void this.runHandler({ request, url, identityKey: senderPublicKey }, requestId);
|
|
151
|
+
});
|
|
152
|
+
try {
|
|
153
|
+
await this.messageCallback?.(message);
|
|
154
|
+
}
|
|
155
|
+
catch (err) {
|
|
156
|
+
peer.stopListeningForGeneralMessages(listenerId);
|
|
157
|
+
this.pendingGeneral.delete(requestId);
|
|
158
|
+
return authError(err);
|
|
159
|
+
}
|
|
160
|
+
return deferred.promise;
|
|
161
|
+
}
|
|
162
|
+
/** Runs the route handler and signs its response back to the peer. */
|
|
163
|
+
async runHandler(ctx, requestId) {
|
|
164
|
+
const pending = this.pendingGeneral.get(requestId);
|
|
165
|
+
if (!pending)
|
|
166
|
+
return;
|
|
167
|
+
try {
|
|
168
|
+
const response = await this.handler(ctx);
|
|
169
|
+
const bodyBytes = [...new Uint8Array(await response.arrayBuffer())];
|
|
170
|
+
const headers = {};
|
|
171
|
+
response.headers.forEach((value, key) => {
|
|
172
|
+
headers[key] = value;
|
|
173
|
+
// Carry non-signed headers (e.g. content-type) through untouched.
|
|
174
|
+
const lk = key.toLowerCase();
|
|
175
|
+
if (!lk.startsWith('x-bsv-') && lk !== 'authorization') {
|
|
176
|
+
pending.passthrough[lk] = value;
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
const payload = buildResponsePayload(requestId, response.status, headers, bodyBytes);
|
|
180
|
+
await this.peer.toPeer(payload, ctx.identityKey);
|
|
181
|
+
}
|
|
182
|
+
catch (err) {
|
|
183
|
+
this.pendingGeneral.delete(requestId);
|
|
184
|
+
pending.deferred.resolve(authError(err));
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/** Builds the Bun `fetch` handler that authenticates every request. */
|
|
189
|
+
export function createAuthenticatedHandler(options) {
|
|
190
|
+
if (!options.wallet)
|
|
191
|
+
throw new Error('createAuthenticatedHandler requires a wallet');
|
|
192
|
+
const transport = new BunTransport(options.handler, options.allowUnauthenticated ?? false);
|
|
193
|
+
const peer = new Peer(options.wallet, transport, options.certificatesToRequest, options.sessionManager ?? new SessionManager());
|
|
194
|
+
transport.setPeer(peer);
|
|
195
|
+
return (request) => transport.handleRequest(request);
|
|
196
|
+
}
|
|
197
|
+
function hexToBytes(hex) {
|
|
198
|
+
return hex ? Utils.toArray(hex, 'hex') : [];
|
|
199
|
+
}
|
|
200
|
+
function json(status, body) {
|
|
201
|
+
return new Response(JSON.stringify(body), {
|
|
202
|
+
status,
|
|
203
|
+
headers: { 'content-type': 'application/json' },
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
function authError(err) {
|
|
207
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
208
|
+
const isAuth = /nonce|signature|session|auth version/i.test(msg);
|
|
209
|
+
return json(isAuth ? 401 : 500, {
|
|
210
|
+
status: 'error',
|
|
211
|
+
code: isAuth ? 'ERR_AUTH_FAILED' : 'ERR_INTERNAL_SERVER_ERROR',
|
|
212
|
+
description: msg,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
export { AUTH_HEADER_KEYS };
|
|
216
|
+
//# sourceMappingURL=transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@1sat/serve",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Bun-native BRC-103/104 mutual-auth transport and BRC-105 payment for HTTP servers, wire-compatible with the BSV Express middleware",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc",
|
|
19
|
+
"dev": "tsc --watch",
|
|
20
|
+
"clean": "rm -rf dist",
|
|
21
|
+
"test": "bun test"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"1sat",
|
|
25
|
+
"bsv",
|
|
26
|
+
"brc-103",
|
|
27
|
+
"brc-104",
|
|
28
|
+
"brc-105",
|
|
29
|
+
"auth",
|
|
30
|
+
"payment",
|
|
31
|
+
"bun"
|
|
32
|
+
],
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"@bsv/sdk": "^2.0.13"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@bsv/sdk": "^2.0.13",
|
|
39
|
+
"@types/bun": "latest",
|
|
40
|
+
"typescript": "^5.9.3"
|
|
41
|
+
}
|
|
42
|
+
}
|