@toon-protocol/rig 2.14.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-VKEUIYQO.js → chunk-4CAOEXGQ.js} +34 -82
- package/dist/chunk-4CAOEXGQ.js.map +1 -0
- package/dist/{chunk-35ALWUDJ.js → chunk-B5ISARMU.js} +2 -10
- package/dist/chunk-B5ISARMU.js.map +1 -0
- package/dist/{chunk-EEUHZNWS.js → chunk-FBIHO3RS.js} +27 -11
- package/dist/chunk-FBIHO3RS.js.map +1 -0
- package/dist/cli/rig.js +35 -24
- package/dist/cli/rig.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +2 -4
- package/dist/{publisher-ftQeZSib.d.ts → publisher-BFcnZeJI.d.ts} +19 -20
- package/dist/standalone/index.d.ts +31 -36
- package/dist/standalone/index.js +2 -2
- package/dist/{standalone-mode-OT63GEPM.js → standalone-mode-X6W2RLTE.js} +3 -3
- package/package.json +3 -2
- package/dist/chunk-35ALWUDJ.js.map +0 -1
- package/dist/chunk-EEUHZNWS.js.map +0 -1
- package/dist/chunk-VKEUIYQO.js.map +0 -1
- /package/dist/{standalone-mode-OT63GEPM.js.map → standalone-mode-X6W2RLTE.js.map} +0 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { c as GitObjectType, P as Publisher, F as FeeRates, b as PublishReceipt } from './publisher-
|
|
2
|
-
export { C as COMMENT_KIND, d as GitObject, G as GitObjectUpload, M as MAINTAINERS_TAG, e as MAX_OBJECT_SIZE, R as REPOSITORY_STATE_KIND, S as StatusKind, U as UnsignedEvent, a as UploadReceipt, f as authorizedStatusAuthors, g as buildComment, h as buildIssue, i as buildPatch, j as buildRepoAnnouncement, k as buildRepoRefs, l as buildStatus, m as createGitBlob, n as createGitCommit, o as createGitTag, p as createGitTree, q as
|
|
1
|
+
import { c as GitObjectType, P as Publisher, F as FeeRates, b as PublishReceipt } from './publisher-BFcnZeJI.js';
|
|
2
|
+
export { C as COMMENT_KIND, d as GitObject, G as GitObjectUpload, M as MAINTAINERS_TAG, e as MAX_OBJECT_SIZE, R as REPOSITORY_STATE_KIND, S as StatusKind, U as UnsignedEvent, a as UploadReceipt, f as authorizedStatusAuthors, g as buildComment, h as buildIssue, i as buildPatch, j as buildRepoAnnouncement, k as buildRepoRefs, l as buildStatus, m as createGitBlob, n as createGitCommit, o as createGitTag, p as createGitTree, q as hashGitObject, r as parseMaintainers } from './publisher-BFcnZeJI.js';
|
|
3
3
|
import '@toon-protocol/core/nip34';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -659,7 +659,7 @@ interface PushFeeEstimate {
|
|
|
659
659
|
objectCount: number;
|
|
660
660
|
/** Total bytes across all planned object bodies. */
|
|
661
661
|
totalObjectBytes: number;
|
|
662
|
-
/**
|
|
662
|
+
/** objectCount × the store route's flat price — smallest asset unit. */
|
|
663
663
|
uploadFee: bigint;
|
|
664
664
|
/** Number of events to publish (refs event + announcement on first push). */
|
|
665
665
|
eventCount: number;
|
|
@@ -853,7 +853,7 @@ interface GitEstimateRequest {
|
|
|
853
853
|
interface GitFeeEstimate {
|
|
854
854
|
objectCount: number;
|
|
855
855
|
totalObjectBytes: number;
|
|
856
|
-
/**
|
|
856
|
+
/** objectCount × the store route's flat price. */
|
|
857
857
|
uploadFee: string;
|
|
858
858
|
/** Events to publish (refs event + announcement on first push). */
|
|
859
859
|
eventCount: number;
|
package/dist/index.js
CHANGED
|
@@ -27,16 +27,15 @@ import {
|
|
|
27
27
|
walkClosure,
|
|
28
28
|
writeGitObject,
|
|
29
29
|
writeGitObjects
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-FBIHO3RS.js";
|
|
31
31
|
import {
|
|
32
32
|
MAX_OBJECT_SIZE,
|
|
33
33
|
createGitBlob,
|
|
34
34
|
createGitCommit,
|
|
35
35
|
createGitTag,
|
|
36
36
|
createGitTree,
|
|
37
|
-
flooredUploadFee,
|
|
38
37
|
hashGitObject
|
|
39
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-B5ISARMU.js";
|
|
40
39
|
import {
|
|
41
40
|
COMMENT_KIND,
|
|
42
41
|
MAINTAINERS_TAG,
|
|
@@ -80,7 +79,6 @@ export {
|
|
|
80
79
|
executePush,
|
|
81
80
|
fetchRemoteState,
|
|
82
81
|
fetchTxBytes,
|
|
83
|
-
flooredUploadFee,
|
|
84
82
|
hashGitObject,
|
|
85
83
|
hexToNpub,
|
|
86
84
|
isSafeRefname,
|
|
@@ -281,33 +281,32 @@ interface PublishReceipt {
|
|
|
281
281
|
/** Fee paid for this publish, in the smallest asset unit. */
|
|
282
282
|
feePaid: bigint;
|
|
283
283
|
}
|
|
284
|
-
/**
|
|
284
|
+
/**
|
|
285
|
+
* Fee rates used by `planPush` for the pre-push estimate.
|
|
286
|
+
*
|
|
287
|
+
* Both figures are FLAT per packet. ADR 0020 (toon-client#452) removed
|
|
288
|
+
* byte-proportional pricing from the protocol: one handler, one price, and an
|
|
289
|
+
* app that wants to charge differently exposes more handlers. A 100-byte and
|
|
290
|
+
* a 100 KB upload to the same store route now cost the same, and the
|
|
291
|
+
* connector charges accordingly regardless of what a client computes — so
|
|
292
|
+
* there is no `uploadFeePerByte` to multiply and no floor to apply, because
|
|
293
|
+
* the route's price is the whole fee rather than a lower bound on one.
|
|
294
|
+
*/
|
|
285
295
|
interface FeeRates {
|
|
286
|
-
/**
|
|
287
|
-
|
|
296
|
+
/**
|
|
297
|
+
* Flat cost per git-object/blob upload (smallest asset unit): the store
|
|
298
|
+
* destination's route price, as reported by the terminating connector's
|
|
299
|
+
* `GET /ilp/routes/price`. The connector gates every paid packet at that
|
|
300
|
+
* price, so an estimate built from it is exactly what a push pays.
|
|
301
|
+
*/
|
|
302
|
+
uploadFee: bigint;
|
|
288
303
|
/**
|
|
289
304
|
* Flat cost per published event (smallest asset unit). Implementations
|
|
290
305
|
* already fold any per-packet route-price floor into this flat value, so
|
|
291
306
|
* estimates using it match the claims actually signed.
|
|
292
307
|
*/
|
|
293
308
|
eventFee: bigint;
|
|
294
|
-
/**
|
|
295
|
-
* FLAT minimum per upload claim (smallest asset unit): the store
|
|
296
|
-
* destination's announced route price. The connector gates every paid
|
|
297
|
-
* packet at the destination route's price — a balance-proof claim
|
|
298
|
-
* advancing the channel by less is rejected (F06) — so each per-upload fee
|
|
299
|
-
* is `max(bytes × uploadFeePerByte, minUploadFee)`. Absent: no floor
|
|
300
|
-
* (pre-floor behavior, e.g. when the peer announces no capability prices).
|
|
301
|
-
*/
|
|
302
|
-
minUploadFee?: bigint;
|
|
303
309
|
}
|
|
304
|
-
/**
|
|
305
|
-
* Per-upload fee: `bytes × ratePerByte`, floored at `minFee` (the
|
|
306
|
-
* destination's announced flat route price — see
|
|
307
|
-
* {@link FeeRates.minUploadFee}). The single shared implementation keeps
|
|
308
|
-
* every estimate site equal to what the publisher actually claims.
|
|
309
|
-
*/
|
|
310
|
-
declare function flooredUploadFee(bytes: number, ratePerByte: bigint, minFee?: bigint): bigint;
|
|
311
310
|
/**
|
|
312
311
|
* Paid transport for `executePush` — implemented by the daemon route
|
|
313
312
|
* handlers (#227) and the standalone embedded client (#228).
|
|
@@ -336,4 +335,4 @@ interface Publisher {
|
|
|
336
335
|
publishEvent(event: UnsignedEvent, relayUrls: string[]): Promise<PublishReceipt>;
|
|
337
336
|
}
|
|
338
337
|
|
|
339
|
-
export { type BlobUpload as B, COMMENT_KIND as C, type FeeRates as F, type GitObjectUpload as G, MAINTAINERS_TAG as M, type Publisher as P, REPOSITORY_STATE_KIND as R, type StatusKind as S, type UnsignedEvent as U, type UploadReceipt as a, type PublishReceipt as b, type GitObjectType as c, type GitObject as d, MAX_OBJECT_SIZE as e, authorizedStatusAuthors as f, buildComment as g, buildIssue as h, buildPatch as i, buildRepoAnnouncement as j, buildRepoRefs as k, buildStatus as l, createGitBlob as m, createGitCommit as n, createGitTag as o, createGitTree as p,
|
|
338
|
+
export { type BlobUpload as B, COMMENT_KIND as C, type FeeRates as F, type GitObjectUpload as G, MAINTAINERS_TAG as M, type Publisher as P, REPOSITORY_STATE_KIND as R, type StatusKind as S, type UnsignedEvent as U, type UploadReceipt as a, type PublishReceipt as b, type GitObjectType as c, type GitObject as d, MAX_OBJECT_SIZE as e, authorizedStatusAuthors as f, buildComment as g, buildIssue as h, buildPatch as i, buildRepoAnnouncement as j, buildRepoRefs as k, buildStatus as l, createGitBlob as m, createGitCommit as n, createGitTag as o, createGitTree as p, hashGitObject as q, parseMaintainers as r };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ToonClientConfig, SignedBalanceProof, PublishEventResult } from '@toon-protocol/client';
|
|
2
|
-
|
|
2
|
+
export { extractArweaveTxId } from '@toon-protocol/client';
|
|
3
|
+
import { U as UnsignedEvent, P as Publisher, F as FeeRates, G as GitObjectUpload, a as UploadReceipt, B as BlobUpload, b as PublishReceipt } from '../publisher-BFcnZeJI.js';
|
|
3
4
|
import '@toon-protocol/core/nip34';
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -412,17 +413,21 @@ interface StandalonePublisherOptions {
|
|
|
412
413
|
channelDestination?: string;
|
|
413
414
|
/** Flat fee per published event (daemon `feePerEvent` convention). Default 1n. */
|
|
414
415
|
eventFee?: bigint;
|
|
415
|
-
/**
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
*
|
|
419
|
-
*
|
|
420
|
-
*
|
|
421
|
-
* The connector gates every paid packet at the destination route's price:
|
|
422
|
-
*
|
|
423
|
-
*
|
|
424
|
-
*
|
|
425
|
-
*
|
|
416
|
+
/**
|
|
417
|
+
* FLAT per-packet route prices for the publish/store destinations, as the
|
|
418
|
+
* payment peer announces them (kind:10032 `capabilities` — e.g.
|
|
419
|
+
* `{capability:'os.publish', address:'g.proxy.relay', price:'1000'}`) or as
|
|
420
|
+
* the terminating connector reports them from `GET /ilp/routes/price`.
|
|
421
|
+
*
|
|
422
|
+
* The connector gates every paid packet at the destination route's price: a
|
|
423
|
+
* balance-proof claim advancing the channel by less is rejected (F06). Since
|
|
424
|
+
* ADR 0020 (toon-client#452) a price is flat per handler, so `store` is the
|
|
425
|
+
* WHOLE upload fee rather than a floor under a per-byte computation — an
|
|
426
|
+
* upload of any size costs it. `publish` still floors {@link eventFee},
|
|
427
|
+
* which remains a caller-chosen flat figure.
|
|
428
|
+
*
|
|
429
|
+
* A destination without a known price prices its packets at 0 here and lets
|
|
430
|
+
* the connector be the one to refuse — this class never invents a rate.
|
|
426
431
|
*/
|
|
427
432
|
routePrices?: {
|
|
428
433
|
publish?: bigint;
|
|
@@ -479,15 +484,7 @@ declare function deriveRouteDestinations(anchor: string): {
|
|
|
479
484
|
publish: string;
|
|
480
485
|
store: string;
|
|
481
486
|
};
|
|
482
|
-
|
|
483
|
-
* Decode the Arweave txId from a store-write FULFILL. The deployed payment
|
|
484
|
-
* proxy returns the store's verbatim HTTP/1.1 response
|
|
485
|
-
* (`{"accept":true,"txId":…}` body); legacy non-proxy providers return bare
|
|
486
|
-
* `base64(utf8(txId))`.
|
|
487
|
-
*
|
|
488
|
-
* @throws {StandalonePublishError} when no valid txId can be extracted.
|
|
489
|
-
*/
|
|
490
|
-
declare function extractArweaveTxId(base64Data: string): string;
|
|
487
|
+
|
|
491
488
|
declare class StandalonePublisher implements Publisher {
|
|
492
489
|
private readonly client;
|
|
493
490
|
private readonly ownsClient;
|
|
@@ -495,7 +492,6 @@ declare class StandalonePublisher implements Publisher {
|
|
|
495
492
|
private readonly storeDestination;
|
|
496
493
|
private readonly channelDestination;
|
|
497
494
|
private readonly eventFee;
|
|
498
|
-
private readonly uploadFeePerByte;
|
|
499
495
|
private readonly routePrices;
|
|
500
496
|
private readonly daemonPort;
|
|
501
497
|
private readonly skipDaemonCheck;
|
|
@@ -604,13 +600,10 @@ declare class StandalonePublisher implements Publisher {
|
|
|
604
600
|
*/
|
|
605
601
|
readWalletChainBalances(fallback?: WalletViewFallback): Promise<WalletChainBalanceInfo[]>;
|
|
606
602
|
/**
|
|
607
|
-
* Fee rates for `planPush` estimation
|
|
608
|
-
*
|
|
609
|
-
*
|
|
610
|
-
*
|
|
611
|
-
* `eventFee` is returned pre-floored at the publish route price, and the
|
|
612
|
-
* store route price rides as `minUploadFee` (the per-upload floor —
|
|
613
|
-
* per-byte pricing can't fold a flat floor into the rate).
|
|
603
|
+
* Fee rates for `planPush` estimation, both flat per packet (ADR 0020),
|
|
604
|
+
* with the announced route prices folded in so the ESTIMATE always equals
|
|
605
|
+
* the CLAIMS: `eventFee` is returned pre-floored at the publish route price,
|
|
606
|
+
* and `uploadFee` IS the store route price.
|
|
614
607
|
*/
|
|
615
608
|
getFeeRates(): Promise<FeeRates>;
|
|
616
609
|
/**
|
|
@@ -619,15 +612,18 @@ declare class StandalonePublisher implements Publisher {
|
|
|
619
612
|
*/
|
|
620
613
|
private effectiveEventFee;
|
|
621
614
|
/**
|
|
622
|
-
* The per-upload claim:
|
|
623
|
-
*
|
|
615
|
+
* The per-upload claim: the store route's flat price, whatever the object's
|
|
616
|
+
* size. Byte-proportional pricing has no successor (ADR 0020) — the route
|
|
617
|
+
* table is the price list — and the connector charges this figure whether
|
|
618
|
+
* the body is 100 bytes or 100 KB.
|
|
624
619
|
*/
|
|
625
620
|
private uploadFee;
|
|
626
621
|
/**
|
|
627
622
|
* Upload one git object as a kind:5094 store write (Git-SHA/Git-Type/Repo
|
|
628
623
|
* tagged — the proven seed-pipeline shape), signing one balance-proof claim
|
|
629
|
-
* for
|
|
630
|
-
*
|
|
624
|
+
* for the store route's flat price
|
|
625
|
+
* ({@link StandalonePublisherOptions.routePrices}) — ADR 0020 prices a
|
|
626
|
+
* packet per handler, not per byte.
|
|
631
627
|
*
|
|
632
628
|
* #368: a blob's `Content-Type` is derived from its path extension (else
|
|
633
629
|
* octet-stream) and sent in the `output` tag, which the store forwards onto
|
|
@@ -642,8 +638,7 @@ declare class StandalonePublisher implements Publisher {
|
|
|
642
638
|
* tags (and an optional `Repo` provenance tag), NOT the Git-SHA/Git-Type
|
|
643
639
|
* tags. Without those the store keeps the bytes verbatim instead of
|
|
644
640
|
* re-deriving a git envelope, which is exactly what the ar.io path manifest
|
|
645
|
-
* needs. One balance-proof claim for
|
|
646
|
-
* floored at the store route's announced price.
|
|
641
|
+
* needs. One balance-proof claim for the store route's flat price.
|
|
647
642
|
*/
|
|
648
643
|
uploadBlob(upload: BlobUpload): Promise<UploadReceipt>;
|
|
649
644
|
/**
|
|
@@ -770,4 +765,4 @@ declare class NonceLock {
|
|
|
770
765
|
release(): void;
|
|
771
766
|
}
|
|
772
767
|
|
|
773
|
-
export { type AcquireLockOptions, type ChannelCloseOutcome, ChannelMapCorruptError, type ChannelMapKey, type ChannelMapRecord, ChannelMapStore, type ChannelMapStoreOptions, type ChannelOpenOutcome, type ChannelSettleOutcome, type CheckDaemonOptions, DEFAULT_DAEMON_PORT, DaemonIdentityConflictError, NonceLock, type PersistedChannelContext, RIG_CHANNEL_MAP_FILENAME, type SignedNostrEvent, StandaloneLockError, type StandaloneMoneyOps, StandalonePublishError, StandalonePublisher, type StandalonePublisherOptions, type ToonClientLike, type WalletChainBalanceInfo, type WalletTokenAmountInfo, type WatermarkEntry, channelStatus, checkDaemonIdentity, defaultDaemonPort, defaultLockDir, deriveRouteDestinations,
|
|
768
|
+
export { type AcquireLockOptions, type ChannelCloseOutcome, ChannelMapCorruptError, type ChannelMapKey, type ChannelMapRecord, ChannelMapStore, type ChannelMapStoreOptions, type ChannelOpenOutcome, type ChannelSettleOutcome, type CheckDaemonOptions, DEFAULT_DAEMON_PORT, DaemonIdentityConflictError, NonceLock, type PersistedChannelContext, RIG_CHANNEL_MAP_FILENAME, type SignedNostrEvent, StandaloneLockError, type StandaloneMoneyOps, StandalonePublishError, StandalonePublisher, type StandalonePublisherOptions, type ToonClientLike, type WalletChainBalanceInfo, type WalletTokenAmountInfo, type WatermarkEntry, channelStatus, checkDaemonIdentity, defaultDaemonPort, defaultLockDir, deriveRouteDestinations, recordKey, resolveChannelPaths };
|
package/dist/standalone/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
StandalonePublisher,
|
|
4
4
|
deriveRouteDestinations,
|
|
5
5
|
extractArweaveTxId
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-4CAOEXGQ.js";
|
|
7
7
|
import {
|
|
8
8
|
ChannelMapCorruptError,
|
|
9
9
|
ChannelMapStore,
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
recordKey,
|
|
20
20
|
resolveChannelPaths
|
|
21
21
|
} from "../chunk-LCYCKWAT.js";
|
|
22
|
-
import "../chunk-
|
|
22
|
+
import "../chunk-B5ISARMU.js";
|
|
23
23
|
export {
|
|
24
24
|
ChannelMapCorruptError,
|
|
25
25
|
ChannelMapStore,
|
|
@@ -11,13 +11,13 @@ import {
|
|
|
11
11
|
import {
|
|
12
12
|
StandalonePublisher,
|
|
13
13
|
deriveRouteDestinations
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-4CAOEXGQ.js";
|
|
15
15
|
import {
|
|
16
16
|
ChannelMapStore,
|
|
17
17
|
RIG_CHANNEL_MAP_FILENAME,
|
|
18
18
|
standaloneForced
|
|
19
19
|
} from "./chunk-LCYCKWAT.js";
|
|
20
|
-
import "./chunk-
|
|
20
|
+
import "./chunk-B5ISARMU.js";
|
|
21
21
|
import {
|
|
22
22
|
DISCOVERY_TIMEOUT_MS,
|
|
23
23
|
MinaChannelUnderivableError,
|
|
@@ -728,4 +728,4 @@ export {
|
|
|
728
728
|
createStandaloneContext,
|
|
729
729
|
resolveNetworkTopology
|
|
730
730
|
};
|
|
731
|
-
//# sourceMappingURL=standalone-mode-
|
|
731
|
+
//# sourceMappingURL=standalone-mode-X6W2RLTE.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toon-protocol/rig",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Git-to-TOON write path core — build git objects and NIP-34 events for the Rig control plane",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Jonathan Green",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"@toon-format/toon": "^1.0.0",
|
|
46
46
|
"@toon-protocol/core": "^3.1.2",
|
|
47
47
|
"nostr-tools": "^2.20.0",
|
|
48
|
-
"@toon-protocol/client": "^0.
|
|
48
|
+
"@toon-protocol/client": "^0.22.0"
|
|
49
49
|
},
|
|
50
50
|
"optionalDependencies": {
|
|
51
51
|
"@ar.io/sdk": "^4.0.3",
|
|
@@ -63,6 +63,7 @@
|
|
|
63
63
|
},
|
|
64
64
|
"scripts": {
|
|
65
65
|
"build": "tsup",
|
|
66
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
66
67
|
"test": "vitest run",
|
|
67
68
|
"test:coverage": "vitest run --coverage"
|
|
68
69
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/objects.ts","../src/publisher.ts"],"sourcesContent":["/**\n * Pure git object construction and SHA-1 envelope hashing.\n *\n * Promoted from `packages/rig-web/tests/e2e/seed/lib/git-builder.ts` (#223) —\n * the proven seed pipeline builders, now the core of the Git-to-TOON write\n * path. Everything here is pure: no network, no signing, no payments.\n * Upload/publish lives with the Publisher (#226).\n *\n * Git object format: `<type> <size>\\0<content>`. The SHA-1 is computed over\n * the full envelope (header + NUL + content); the `body` (content only) is\n * what gets uploaded to Arweave.\n */\n\nimport { createHash } from 'node:crypto';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** All git object types TOON can carry. */\nexport type GitObjectType = 'blob' | 'tree' | 'commit' | 'tag';\n\nexport interface GitObject {\n /** SHA-1 hex digest computed over full git envelope */\n sha: string;\n /** Full git object (header + null + content) */\n buffer: Buffer;\n /** Body only (content after the null byte) — this is what gets uploaded */\n body: Buffer;\n}\n\n/**\n * Maximum uploadable git object body size: 95KB safety margin under the\n * 100KB free tier (R10-005). Larger objects are a hard error in v1.\n */\nexport const MAX_OBJECT_SIZE = 95 * 1024;\n\n/**\n * Git's universal empty-blob SHA-1: the object for a zero-byte file.\n *\n * It is the ONLY zero-byte object git can produce (trees, commits, and tags\n * are never empty) and it always has this exact constant value. The store\n * rejects a zero-byte kind:5094 blob upload as malformed (F00), so `rig` never\n * uploads this object — it is skipped on push and synthesized locally on\n * clone/fetch (both keyed off an ACTUAL zero-length body, never a heuristic).\n */\nexport const EMPTY_BLOB_SHA = 'e69de29bb2d1d6434b8b29ae775ad8c2e48c5391';\n\n// ---------------------------------------------------------------------------\n// Envelope hashing\n// ---------------------------------------------------------------------------\n\n/**\n * Wrap a raw object body in the git envelope (`<type> <size>\\0`) and compute\n * its SHA-1. This is exactly what `git hash-object -t <type>` does.\n */\nexport function hashGitObject(type: GitObjectType, body: Buffer): GitObject {\n const header = Buffer.from(`${type} ${body.length}\\0`);\n const fullObject = Buffer.concat([header, body]);\n const sha = createHash('sha1').update(fullObject).digest('hex');\n return { sha, buffer: fullObject, body };\n}\n\n// ---------------------------------------------------------------------------\n// Git object construction\n// ---------------------------------------------------------------------------\n\n/**\n * Construct a git blob object and compute its SHA-1.\n *\n * Format: blob <size>\\0<content>\n * SHA is over the full envelope; body is content only (for upload).\n */\nexport function createGitBlob(content: string): GitObject {\n return hashGitObject('blob', Buffer.from(content, 'utf-8'));\n}\n\n/**\n * Construct a git tree object from sorted entries.\n *\n * Format: tree <size>\\0<entries>\n * Each entry: <mode> <name>\\0<20-byte-raw-sha1>\n * Entries MUST be sorted by name (byte-wise).\n */\nexport function createGitTree(\n entries: { mode: string; name: string; sha: string }[]\n): GitObject {\n // Git sorts tree entries by raw byte order (NOT locale-aware)\n const sorted = [...entries].sort((a, b) =>\n a.name < b.name ? -1 : a.name > b.name ? 1 : 0\n );\n\n const entryBuffers: Buffer[] = [];\n for (const entry of sorted) {\n const modeAndName = Buffer.from(`${entry.mode} ${entry.name}\\0`);\n // Raw 20-byte SHA-1 (NOT hex)\n const rawSha = Buffer.from(entry.sha, 'hex');\n entryBuffers.push(Buffer.concat([modeAndName, rawSha]));\n }\n\n return hashGitObject('tree', Buffer.concat(entryBuffers));\n}\n\n/**\n * Construct a git commit object.\n *\n * Format: commit <size>\\0tree <tree-sha>\\n[parent ...]\\nauthor ...\\ncommitter ...\\n\\n<message>\n * Tree/parent SHAs are hex-encoded (40 chars) in commits, unlike tree entries.\n */\nexport function createGitCommit(opts: {\n treeSha: string;\n parentSha?: string;\n authorName: string;\n authorPubkey: string;\n message: string;\n timestamp: number;\n}): GitObject {\n const lines = [\n `tree ${opts.treeSha}`,\n ...(opts.parentSha ? [`parent ${opts.parentSha}`] : []),\n `author ${opts.authorName} <${opts.authorPubkey}@nostr> ${opts.timestamp} +0000`,\n `committer ${opts.authorName} <${opts.authorPubkey}@nostr> ${opts.timestamp} +0000`,\n '',\n opts.message,\n ];\n return hashGitObject('commit', Buffer.from(lines.join('\\n'), 'utf-8'));\n}\n\n/**\n * Construct an annotated git tag object.\n *\n * Format: tag <size>\\0object <sha>\\ntype <type>\\ntag <name>\\ntagger ...\\n\\n<message>\n * The tagged object is usually a commit, but git allows tagging any object\n * type (including another tag).\n */\nexport function createGitTag(opts: {\n /** SHA-1 of the object being tagged (hex, 40 chars) */\n objectSha: string;\n /** Type of the tagged object (usually 'commit') */\n objectType: GitObjectType;\n /** Tag name, e.g. 'v1.0.0' */\n tagName: string;\n taggerName: string;\n taggerPubkey: string;\n message: string;\n timestamp: number;\n}): GitObject {\n const lines = [\n `object ${opts.objectSha}`,\n `type ${opts.objectType}`,\n `tag ${opts.tagName}`,\n `tagger ${opts.taggerName} <${opts.taggerPubkey}@nostr> ${opts.timestamp} +0000`,\n '',\n opts.message,\n ];\n return hashGitObject('tag', Buffer.from(lines.join('\\n'), 'utf-8'));\n}\n","/**\n * Publisher — the paid-write seam between push planning (this package) and\n * the two transport implementations that follow it in epic #222:\n *\n * 1. daemon (#227): client-mcp ControlClient → toon-clientd loopback\n * /git/* routes, backed by `ClientRunner.publish`/`uploadBlob` (the\n * production paid-publish path — apex channel, signBalanceProof, flat\n * per-event fee).\n * 2. standalone (#228): an embedded ToonClient constructed from a\n * mnemonic, uploading git objects as kind:5094 store writes with\n * Git-SHA/Git-Type/Repo tags (the proven seed-pipeline shape) and\n * publishing NIP-34 events through the relay.\n *\n * The interface is deliberately minimal so both fit:\n *\n * - `uploadGitObject` takes the raw object body (content only — no git\n * envelope header; the store re-derives the SHA envelope from the\n * Git-Type/Git-SHA tags) and returns the Arweave txId plus the fee paid.\n * - `publishEvent` takes an UNSIGNED event template — signing stays with\n * the implementation (the daemon-held key never leaves the daemon; the\n * standalone impl signs with its own keypair). Relay URLs are plural\n * from day one (forward-compat for parked #84/#92; size 1 today).\n * - `getFeeRates` exposes what `planPush` needs for the pre-push estimate:\n * a per-byte upload rate (seed pipeline bids bytes × rate) and a flat\n * per-event publish fee (the daemon charges `apex.feePerEvent` regardless\n * of event size).\n *\n * All fees are bigint in the smallest asset unit (matches `@toon-protocol/client`\n * channel math); HTTP transports serialize them as strings and convert at\n * the boundary.\n */\n\nimport type { UnsignedEvent } from './nip34-events.js';\nimport type { GitObjectType } from './objects.js';\n\n/** A git object queued for upload to Arweave via the paid store path. */\nexport interface GitObjectUpload {\n /** Full 40-hex SHA-1 (over the git envelope — see `hashGitObject`). */\n sha: string;\n type: GitObjectType;\n /** Raw object body (content only, no `<type> <size>\\0` header). */\n body: Buffer;\n /** Repository identifier — becomes the `Repo` tag on the store write. */\n repoId: string;\n /**\n * Path the blob was reached by in the tree (#368), if known. Its extension\n * derives the `Content-Type` sent in the store write's `output` tag so a\n * gateway serves the blob as its real media type instead of\n * `application/octet-stream`. Absent (or a non-blob object) → octet-stream.\n */\n path?: string;\n}\n\n/**\n * A NON-git blob queued for upload to Arweave with an explicit `Content-Type`\n * (#368): the ar.io path manifest that turns a pushed repo into a permaweb\n * site. Unlike {@link GitObjectUpload} it carries no `Git-SHA`/`Git-Type`\n * tags, so the store stores the raw bytes verbatim (no git-envelope\n * re-derivation) — exactly what a manifest needs.\n */\nexport interface BlobUpload {\n /** Raw bytes to store. */\n body: Buffer;\n /** MIME type sent in the store write's `output` tag. */\n contentType: string;\n /** Optional repository identifier for provenance (`Repo` tag). */\n repoId?: string;\n}\n\n/** Receipt for one uploaded git object. */\nexport interface UploadReceipt {\n /** Arweave transaction ID the object is retrievable under. */\n txId: string;\n /** Fee paid for this upload, in the smallest asset unit. */\n feePaid: bigint;\n}\n\n/** Receipt for one published Nostr event. */\nexport interface PublishReceipt {\n /** Event ID as accepted by the relay(s). */\n eventId: string;\n /** Fee paid for this publish, in the smallest asset unit. */\n feePaid: bigint;\n}\n\n/** Fee rates used by `planPush` for the pre-push estimate. */\nexport interface FeeRates {\n /** Upload cost per body byte (smallest asset unit). */\n uploadFeePerByte: bigint;\n /**\n * Flat cost per published event (smallest asset unit). Implementations\n * already fold any per-packet route-price floor into this flat value, so\n * estimates using it match the claims actually signed.\n */\n eventFee: bigint;\n /**\n * FLAT minimum per upload claim (smallest asset unit): the store\n * destination's announced route price. The connector gates every paid\n * packet at the destination route's price — a balance-proof claim\n * advancing the channel by less is rejected (F06) — so each per-upload fee\n * is `max(bytes × uploadFeePerByte, minUploadFee)`. Absent: no floor\n * (pre-floor behavior, e.g. when the peer announces no capability prices).\n */\n minUploadFee?: bigint;\n}\n\n/**\n * Per-upload fee: `bytes × ratePerByte`, floored at `minFee` (the\n * destination's announced flat route price — see\n * {@link FeeRates.minUploadFee}). The single shared implementation keeps\n * every estimate site equal to what the publisher actually claims.\n */\nexport function flooredUploadFee(\n bytes: number,\n ratePerByte: bigint,\n minFee?: bigint\n): bigint {\n const fee = BigInt(bytes) * ratePerByte;\n const min = minFee ?? 0n;\n return fee > min ? fee : min;\n}\n\n/**\n * Paid transport for `executePush` — implemented by the daemon route\n * handlers (#227) and the standalone embedded client (#228).\n *\n * Implementations must be safe to call sequentially (uploads are issued one\n * at a time in dependency-safe order) and should throw on any failure —\n * `executePush` does not retry; a crashed push is resumed by re-planning\n * (content-addressed uploads make the retry idempotent).\n */\nexport interface Publisher {\n /** Current fee rates for estimation (may be queried before every plan). */\n getFeeRates(): Promise<FeeRates>;\n /** Upload one git object body to Arweave; paid. */\n uploadGitObject(upload: GitObjectUpload): Promise<UploadReceipt>;\n /**\n * Upload one raw blob (no git envelope) with an explicit `Content-Type`;\n * paid. Used by `rig site` (#368) for the ar.io path manifest. Optional so\n * transports that only move git objects (and pre-#368 test fakes) need not\n * implement it — `rig site` requires it and errors clearly when absent.\n */\n uploadBlob?(upload: BlobUpload): Promise<UploadReceipt>;\n /**\n * Sign (implementation-held key) and pay-to-publish one event to the\n * given relay(s).\n */\n publishEvent(\n event: UnsignedEvent,\n relayUrls: string[]\n ): Promise<PublishReceipt>;\n}\n"],"mappings":";AAaA,SAAS,kBAAkB;AAsBpB,IAAM,kBAAkB,KAAK;AAW7B,IAAM,iBAAiB;AAUvB,SAAS,cAAc,MAAqB,MAAyB;AAC1E,QAAM,SAAS,OAAO,KAAK,GAAG,IAAI,IAAI,KAAK,MAAM,IAAI;AACrD,QAAM,aAAa,OAAO,OAAO,CAAC,QAAQ,IAAI,CAAC;AAC/C,QAAM,MAAM,WAAW,MAAM,EAAE,OAAO,UAAU,EAAE,OAAO,KAAK;AAC9D,SAAO,EAAE,KAAK,QAAQ,YAAY,KAAK;AACzC;AAYO,SAAS,cAAc,SAA4B;AACxD,SAAO,cAAc,QAAQ,OAAO,KAAK,SAAS,OAAO,CAAC;AAC5D;AASO,SAAS,cACd,SACW;AAEX,QAAM,SAAS,CAAC,GAAG,OAAO,EAAE;AAAA,IAAK,CAAC,GAAG,MACnC,EAAE,OAAO,EAAE,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,IAAI;AAAA,EAC/C;AAEA,QAAM,eAAyB,CAAC;AAChC,aAAW,SAAS,QAAQ;AAC1B,UAAM,cAAc,OAAO,KAAK,GAAG,MAAM,IAAI,IAAI,MAAM,IAAI,IAAI;AAE/D,UAAM,SAAS,OAAO,KAAK,MAAM,KAAK,KAAK;AAC3C,iBAAa,KAAK,OAAO,OAAO,CAAC,aAAa,MAAM,CAAC,CAAC;AAAA,EACxD;AAEA,SAAO,cAAc,QAAQ,OAAO,OAAO,YAAY,CAAC;AAC1D;AAQO,SAAS,gBAAgB,MAOlB;AACZ,QAAM,QAAQ;AAAA,IACZ,QAAQ,KAAK,OAAO;AAAA,IACpB,GAAI,KAAK,YAAY,CAAC,UAAU,KAAK,SAAS,EAAE,IAAI,CAAC;AAAA,IACrD,UAAU,KAAK,UAAU,KAAK,KAAK,YAAY,WAAW,KAAK,SAAS;AAAA,IACxE,aAAa,KAAK,UAAU,KAAK,KAAK,YAAY,WAAW,KAAK,SAAS;AAAA,IAC3E;AAAA,IACA,KAAK;AAAA,EACP;AACA,SAAO,cAAc,UAAU,OAAO,KAAK,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC;AACvE;AASO,SAAS,aAAa,MAWf;AACZ,QAAM,QAAQ;AAAA,IACZ,UAAU,KAAK,SAAS;AAAA,IACxB,QAAQ,KAAK,UAAU;AAAA,IACvB,OAAO,KAAK,OAAO;AAAA,IACnB,UAAU,KAAK,UAAU,KAAK,KAAK,YAAY,WAAW,KAAK,SAAS;AAAA,IACxE;AAAA,IACA,KAAK;AAAA,EACP;AACA,SAAO,cAAc,OAAO,OAAO,KAAK,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC;AACpE;;;AC5CO,SAAS,iBACd,OACA,aACA,QACQ;AACR,QAAM,MAAM,OAAO,KAAK,IAAI;AAC5B,QAAM,MAAM,UAAU;AACtB,SAAO,MAAM,MAAM,MAAM;AAC3B;","names":[]}
|