@arkade-os/swap 0.0.6 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -116,13 +116,22 @@ uncached discovery.
116
116
  Neither subpath adds a dependency: they take the SDK's structural `SQLExecutor` / `RealmLike`
117
117
  handles, so you pass the database you already opened.
118
118
 
119
+ All four carry both record types: asset swaps and the monitored RFQ swaps
120
+ (`saveRfqSwap` / `getRfqSwap` / `getAllRfqSwaps` / `removeRfqSwap`). Each keeps them in a store of their own — a
121
+ second object store on IndexedDB, an `…rfq_swaps` table on SQLite, the `ArkadeRfqSwap` class on
122
+ Realm — since the two record types have different keys and no consumer wants them interleaved.
123
+
119
124
  **Records are stored whole.** The SQLite and Realm backends serialize each record to **JSON** in a
120
- `data` column, with only `status` / `createdAt` mapped out for querying so a field they do not
121
- know about survives, which is what the `quote`-shaped extension in `MIGRATION.md` relies on. JSON is
125
+ `data` column, with only `status` / `createdAt` (and an RFQ record's `state` / `updatedAt`) mapped
126
+ out for querying — so a field they do not know about survives, which is what the `quote`-shaped
127
+ extension in `MIGRATION.md` relies on. It is also what keeps an RFQ record's corridor `profile`
128
+ intact: `profile.hashlock` is a nested object holding the payment hash and any preimage material, and
129
+ a field-mapped backend is exactly what would lose it. JSON is
122
130
  the boundary, though, and it is narrower than IndexedDB's structured clone: a `Date` in a
123
131
  consumer-added field comes back an ISO **string**, a `Set` or `Map` comes back empty, and a `bigint`
124
- makes `saveSwap` **throw**. `AssetSwap` itself is JSON-safe by design (amounts are strings); keep
125
- your own added fields that way too.
132
+ makes `saveSwap` **throw**. `AssetSwap` and `RfqSwapRecord` are both JSON-safe by design (amounts are
133
+ strings, binary is hex), and a corridor `profile` is plain JSON by the handler contract; keep your own
134
+ added fields — and any corridor profile you write — that way too.
126
135
 
127
136
  ### SQLite
128
137
 
@@ -169,9 +178,15 @@ const realm = await Realm.open({
169
178
  const swaps = new RealmAssetSwapRepository(realm);
170
179
  ```
171
180
 
172
- Three classes land in your Realm namespace: `ArkadeAssetSwap`, `ArkadeAssetSwapScannedTxid`,
173
- `ArkadeAssetSwapMarketsCache`. Unlike SQLite there is no prefix option — a Realm schema name is
174
- baked into the schema objects you register — so reconcile against your own models by name.
181
+ Four classes land in your Realm namespace: `ArkadeAssetSwap`, `ArkadeRfqSwap`,
182
+ `ArkadeAssetSwapScannedTxid`, `ArkadeAssetSwapMarketsCache`. Unlike SQLite there is no prefix option
183
+ — a Realm schema name is baked into the schema objects you register — so reconcile against your own
184
+ models by name.
185
+
186
+ `ArkadeRfqSwap` arrived after the other three. **If you already shipped them, add it and bump
187
+ `schemaVersion` again**: Realm creates schemas at open, so a config still listing three fails on the
188
+ first RFQ read rather than at open. SQLite needs nothing — its DDL runs `CREATE TABLE IF NOT EXISTS`
189
+ on every init, so the table appears on the next operation.
175
190
 
176
191
  ## Creating an offer
177
192
 
@@ -290,7 +305,9 @@ message anywhere: **acceptance is funding**.
290
305
  offline. The solver observes the funding on-chain, pays the invoice, and claims with the
291
306
  preimage — which lands publicly in the claim witness as the receipt. A failed swap refunds by
292
307
  covenant to the trader's address, pushable by anyone, no trader keys or state.
293
- - **Arkade ↔ arkade** (BTC↔asset, asset↔asset): the trader accepts a quote by creating and funding
308
+ - **Arkade ↔ arkade** (BTC↔asset, asset↔asset): an arkade asset leg names the asset id itself —
309
+ `arkade:<68-hex>`, built with `arkadeAssetLeg` (the deprecated coarse `ARKADE_ASSET` is served by
310
+ no solver). The trader accepts a quote by creating and funding
294
311
  an **offer** (layer 1) bound to the quoted terms before `valid_until`. The offer covenant only
295
312
  releases the deposit to a fill that delivers the quoted amount, so the solver fills or nothing
296
313
  moves; an unfilled offer is cancelled cooperatively. The quote wire shape ships here; the
@@ -556,6 +573,103 @@ terminal: the lockup stays funded and watched, a solver claim still ends the swa
556
573
  `pending`. The manager reports the same state when nothing is wired to act (`enableAutoActions:
557
574
  false`, or no callbacks) and the window has passed.
558
575
 
576
+ **The two claim callbacks may be omitted.** `setCallbacks` accepts
577
+ `AvailableRfqSwapManagerCallbacks` — the full contract with `claimOnchain` and `claimLockup`
578
+ optional — so a consumer driving only lightning sends installs neither instead of stubbing them to
579
+ throw. Dispatch is already kind-gated, so neither is reachable there. `saveSwap` is optional too
580
+ (see below); `refundArkade` stays required.
581
+
582
+ `RfqSwapManagerCallbacks` itself is unchanged and still means "fully wired", so a helper taking one
583
+ and calling `claimOnchain` keeps its guarantee; only the parameter widens, which every existing
584
+ caller satisfies. What moves from compile time to runtime is bought back as a **block**: a kind
585
+ whose claim is missing reports `needs_counterparty` naming the gap, non-terminal and re-evaluated
586
+ every pass, lifted the moment `setCallbacks` supplies it. Not `failed` — `setCallbacks` is
587
+ installable late by design, and a terminal state would foreclose the late wiring this exists for.
588
+ A manager with *no* callbacks at all keeps today's manual mode on the L1 half: it reports
589
+ `claimable` and you act by hand.
590
+
591
+ **Take `arkadeRefunder` rather than assembling `refundArkade` by hand.** It composes the atomic
592
+ push and keeps the three rules the manager relies on structural instead of documented — an empty
593
+ lockup returns `null`, and both `RefundNotLocallyPossibleError` and `LockupNeedsRecoveryError`
594
+ propagate untouched.
595
+
596
+ ```ts
597
+ manager.setCallbacks({
598
+ // `repository` is how it reaches `profile.signer`: the live swap the manager
599
+ // passes carries no descriptor, so the refund key is resolved by `rfqId`.
600
+ refundArkade: arkadeRefunder({ ark, indexer, wallet, repository }),
601
+ saveSwap,
602
+ });
603
+ ```
604
+
605
+ Keep the covenant on the swap (`request*`'s `script`, as a record's `lockup`): the refund is built
606
+ from it, and a swap carrying only `lockupPkScript` is refused rather than pushed.
607
+
608
+ ### Let the manager own the records
609
+
610
+ Give `RfqSwapManager` a `repository` and it persists RFQ swaps itself — the restore loop, the
611
+ retention pass and every write, none of which a consumer has to compose:
612
+
613
+ ```ts
614
+ const manager = new RfqSwapManager({
615
+ indexer,
616
+ contracts: await wallet.getContractManager(),
617
+ repository, // any AssetSwapRepository
618
+ });
619
+ manager.setCallbacks({ refundArkade, claimLockup });
620
+
621
+ // Rebuild what was stored: retention first, then each record's covenant from
622
+ // its own contract row, then `rebuildRfqSwap`. No caller input at all.
623
+ const { restored, failed, pruned } = await manager.restoreFromRepository();
624
+ await manager.start();
625
+
626
+ // A NEW swap arrives with the request-time half a live record cannot carry.
627
+ await manager.addSwap(swap, {
628
+ kind: "lightning_send",
629
+ lockupAddress: request.lockupAddress,
630
+ profile: rfqSecretsProfile(secrets, paymentHash),
631
+ fundingArkTxid,
632
+ amount,
633
+ });
634
+ ```
635
+
636
+ That second argument is the whole point. Composing the write by hand runs into an **origin trap**:
637
+ `updateRfqSwapRecord(record, swap)` needs the record that does not exist yet, and
638
+ `createRfqSwapRecord(origin, swap)` needs request-time facts the live swap never carried — so a
639
+ swap's *first* record cannot be built from the swap alone. `addSwap`'s `origin` is where those
640
+ facts arrive, and the manager keeps them for the swap's life. Omit it and one of two things
641
+ happens: the store already holds a record, which *is* the origin, and it is read back; or it does
642
+ not, and you get `RfqSwapOriginRequired` at the door rather than an unwritable record a pass later.
643
+ An origin whose `kind` or `lockupAddress` is not this swap's is refused at that same door, for the
644
+ same reason: the write that would catch it happens a pass later, with the funding broadcast.
645
+ `start(swaps)` applies the same rule and is otherwise unchanged. Restored swaps carry their own.
646
+
647
+ `restoreFromRepository` returns three disjoint lists, and every stored record is in exactly one.
648
+ A record that cannot be rebuilt — no contract row (`LockupContractMissing`), covenant params that
649
+ do not derive the funded address, a corridor with no handler — lands in `failed` with its error and
650
+ stays in the store; it never strands the others and it is never silently dropped. `pruned` names
651
+ what retention removed: terminal and more than `RFQ_SWAP_RETENTION_SECONDS` past `updatedAt`, never
652
+ `needs_counterparty`. Retention runs first, so a retired record costs no contract lookup on its way
653
+ out; `pruneRetiredSwaps()` is public for a process that wants it on its own cadence. Pass
654
+ `{ params }` to take covenants from somewhere other than the contract store.
655
+
656
+ **Two sinks, and both gate.** With a repository wired the canonical `RfqSwapRecord` is written
657
+ first, then `saveSwap` if one is installed, and the pass counts as persisted only when both
658
+ succeeded — which is exactly today's rule for `saveSwap`, applied to whichever sinks exist. A
659
+ rejection from either leaves the record dirty and monitored, so waiters stay unsettled and a
660
+ terminal swap is not finalized until the write it claims lands. A failed canonical write skips
661
+ `saveSwap` entirely: projecting a state the record of record has just refused would put the
662
+ secondary sink ahead of the primary. If your `saveSwap` writes that same repository by hand, delete
663
+ the duplicate when you wire the dep — otherwise every pass writes twice — and keep the callback for
664
+ genuinely secondary sinks. With neither wired, state stays in memory and dies with the process.
665
+
666
+ **Terminal records name the transaction that ended them.** `RfqSwap.lockupSpendArkTxids` is
667
+ stamped from the chain read that resolved the swap — the solver's claim on a send leg, its reclaim
668
+ on a receive one, the trader's own claim when a receive settles. Nothing local produces those
669
+ transactions, so no other field can name them, and without the stamp the only way to find them is
670
+ another lockup read per terminal swap. Absent when the indexer named the checkpoint but not the ark
671
+ transaction: fewer txids beats a wrong one.
672
+
559
673
  `preimageForSwapRecord` is the read path to wire, not a hand-rolled `contractPreimage` call: it
560
674
  knows which of the record's fields are derivation inputs, and it verifies the result against
561
675
  `paymentHash`. A caller that forgets to pass the salt gets a _wrong_ preimage from a wallet that can
@@ -640,6 +754,62 @@ through their stored `preimageHex` or their HD descriptor, and `DB_VERSION` is u
640
754
 
641
755
  Notes from before 0.0.1, kept for consumers who tracked the branch.
642
756
 
757
+ - **`RfqSwapManager` can own its own persistence.** New optional
758
+ `RfqSwapManagerDeps.repository`, new `restoreFromRepository()` and `pruneRetiredSwaps()`, and
759
+ `addSwap(swap, origin?)` gains an optional second argument. Nothing narrows and nothing is
760
+ removed, so no existing caller changes: without a repository the manager persists through
761
+ `saveSwap` exactly as before. Two things to know if you wire it. `saveSwap` becomes a **second**
762
+ sink rather than the only one — it still gates waiters and finalization, so its semantics are
763
+ unchanged, but a callback that writes the same repository by hand now double-writes and should
764
+ drop the duplicate. And `addSwap` for a swap the store has never seen throws
765
+ `RfqSwapOriginRequired` unless you pass its origin, which is the only way its first record can be
766
+ written at all.
767
+ - **`saveSwap` is optional at installation**, alongside the two claims — the same
768
+ `AvailableRfqSwapManagerCallbacks` relaxation extended one field. Omit it with a repository wired
769
+ and the record store is the only sink; omit both and state is process-local, which is what a
770
+ manager with no callbacks already did.
771
+ - **`RfqSwap` and `RfqSwapRecord` gained `lockupSpendArkTxids?: string[]`** — the ark transactions
772
+ that spent the lockup, stamped by the manager from the chain read that ended the swap. Optional
773
+ and additive: no repository version bump, and a backend storing records whole already carries it.
774
+ - **`RfqSwapState`, `RFQ_SWAP_TERMINAL_STATES` and `isRfqSwapTerminal` moved to
775
+ `src/rfqSwapState.ts`** so the record layer can read them without importing the manager at
776
+ runtime. `swapManager.ts` re-exports all three and the package entry point is unchanged, so no
777
+ import path breaks.
778
+ - **`rfqSwapOriginOf(record)` is new** — a record's immutable half on its own. A record *is* an
779
+ origin plus manager state, so passing one where an origin is wanted type-checks and quietly
780
+ carries the old `failure`, `blockedReason` and `refundArkTxid` past `managerState`, which can
781
+ only set those fields and never clear them. Use this instead of spreading the record.
782
+ - **`arkadeRefunder({ ark, indexer, wallet, repository })` ships the `refundArkade` wiring** that
783
+ was prose in two places. New export, nothing removed.
784
+ - **`rfqSwapActivityInputs({ repository, indexer })` derives `SwapActivityInput[]` from the record
785
+ store** — the correlation helper `activity.ts` promised. `SwapActivityInput["kind"]` is now
786
+ `RfqSwapRecord["kind"]` rather than a literal union repeating it; source-compatible. Corridor
787
+ handlers gained an optional `activityTxids(profile)` so a leg's own claim txid comes from the
788
+ handler instead of a kind switch. The `indexer` is optional and consulted only for what a record
789
+ cannot answer: a record predating `fundingArkTxid`, and the counterparty's spend on a swap no
790
+ refund of ours ended. An unreachable indexer costs that record its extra txids, never a throw.
791
+ - **`setCallbacks` takes `AvailableRfqSwapManagerCallbacks`** — `RfqSwapManagerCallbacks` with the
792
+ two kind-gated claims optional. Nothing breaks: the strict interface is untouched and the widened
793
+ parameter accepts every existing caller. A consumer driving one kind stops stubbing the claims it
794
+ cannot reach; in exchange, a missing claim blocks at runtime (`needs_counterparty`, non-terminal)
795
+ instead of being unrepresentable.
796
+ - **The repository interface is at version `4`.** It gained
797
+ `getRfqSwap(rfqId): Promise<RfqSwapRecord | undefined>` — every backend is already keyed by
798
+ `rfqId`, so a consumer updating one record no longer scans them all. A miss returns `undefined`;
799
+ retention prunes terminal records, so absence is ordinary. All four in-tree backends implement it
800
+ and `DB_VERSION` is unchanged; a custom implementor adds the two-line read and bumps its own
801
+ `version` to `4`.
802
+ - **`RfqSwapOrigin` gained `fundingArkTxid?`** — the ark transaction that funded the lockup. It is
803
+ origin, not manager state: the caller broadcasts the funding and knows the txid, while the manager
804
+ watches the lockup by script and never learns it. Optional and stored whole, so no migration.
805
+ Consumers stashing it in `profile` should move it: `profile` is merged as
806
+ `{ ...profile, ...handler.project(swap) }` on every write, so a key a corridor also projects is
807
+ silently overwritten.
808
+ - **`readLockupFate` names the spends it observed.** `claimed` and `returned` now carry
809
+ `spends: readonly LockupSpend[]`, one per spent lockup output, with the `checkpointTxid` that
810
+ `spentBy` names and the `arkTxid` that rode it. History correlation wants `arkTxid`; the
811
+ checkpoint txid is the wrong value to correlate on alone. `unknown` and `open` claim no spend.
812
+
643
813
  - **Every derived address changed again, in both corridors — the unilateral ladder was re-spaced.**
644
814
  `unilateralRefundDelay` now sits **level with** `claimDelay` instead of one 512s step above it,
645
815
  and `unilateralRefundWithoutReceiverDelay` sits `SOLO_REFUND_HEADROOM_SECONDS` (4096s, newly
@@ -719,10 +889,100 @@ scanned? })` — the server key is required because a spend is classified by reb
719
889
  - **A spend that cannot be classified is no longer restored as `fulfilled`.** It leaves the funding
720
890
  txid unanswered so a later scan decides it. Records are never written on a guess.
721
891
  - **`AssetSwap` gained `signingDescriptor?`**, and `preimageHex` now means "P that cannot be
722
- re-derived" — caller-supplied, or minted for a static descriptor. The repository version stays
723
- `1` the package is unreleased, so there is no stored record to migrate — but a field-mapped
724
- backend must persist the record whole: silently dropping `preimageHex` leaves a static swap
725
- permanently unclaimable.
892
+ re-derived" — caller-supplied, or minted for a static descriptor. A field-mapped backend must
893
+ persist the record whole: silently dropping `preimageHex` leaves a static swap permanently
894
+ unclaimable.
895
+ - **The repository interface is at version `3`.** It gained `saveRfqSwap` / `getAllRfqSwaps` /
896
+ `removeRfqSwap` for monitored RFQ swaps, and the IndexedDB backend a matching `rfqSwaps` object
897
+ store at `DB_VERSION` 2. Version `2` was the shape 0.0.5 released — swaps, scan cursor, markets,
898
+ with `preimageSaltHex` on the swap record — and `DB_VERSION` was 1 there, so this is the database's
899
+ first version increase. The bump is deliberate: an implementor must acknowledge the new methods
900
+ rather than silently satisfy an older shape. Existing databases upgrade in place: the new store is
901
+ added and the three original ones are untouched. **`DB_VERSION` 2 is a one-way door** — a browser
902
+ whose database has upgraded cannot be rolled back to 0.0.5, which opens it at version 1 and fails
903
+ `VersionError` across the whole swap store, not just the RFQ half. Store RFQ records whole for the
904
+ same reason as above: what is in one is what nothing else can recover — the manager's own state,
905
+ and, inside the corridor's `profile`, its keys and its gates.
906
+ - **An RFQ record's keys live in its corridor's `profile`, under two keys.** `profile.signer` holds
907
+ `signingDescriptor` — which wallet key signs this leg, on any corridor. `profile.hashlock` holds
908
+ `paymentHash` (the covenant binds `hash160` of it, which is one-way) plus, **only on legs we
909
+ claim**, `preimageHex` or `preimageSaltHex`. The record's own half — `kind`, `lockupAddress`,
910
+ `amount`, the manager's state — recovers nothing on its own, so a backend that drops either nested
911
+ object loses the signer or the claim secret exactly as one dropping `preimageHex` used to. Two keys
912
+ rather than one because a hashlock belongs to a corridor and a signer does not: a corridor that
913
+ settles without a preimage still has a leg to sign and refund.
914
+
915
+ ```ts
916
+ // In. One call per leg, whatever that leg's provisioning produced — never
917
+ // hand-mapped: copying `signingDescriptor` and `preimageHex` across by hand
918
+ // drops the salt a static wallet's P derives from, and the swap is
919
+ // unclaimable with nothing to say so until claim time.
920
+ const record = createRfqSwapRecord(
921
+ {
922
+ kind: "lightning_receive",
923
+ lockupAddress: result.address,
924
+ profile: {
925
+ ...rfqSecretsProfile(result.secrets, result.treeParams.paymentHash),
926
+ expectedAmount: result.expectedAmount,
927
+ payoutAddress: result.payoutAddress,
928
+ },
929
+ },
930
+ swap,
931
+ );
932
+
933
+ // Out, and WHICH reader depends on the leg. The refund signer, on any leg:
934
+ const sender = await senderIdentityForSwapRecord(wallet, rfqSignerOf(record)!);
935
+ // P, only where we claim — `lightning_receive`, `onchain_send`:
936
+ const claim = rfqClaimSecretOf(record);
937
+ if (claim) await preimageForSwapRecord(wallet, claim); // hash-checked
938
+ ```
939
+
940
+ - **`lightning_send` has a payment hash and no preimage**, so `rfqClaimSecretOf` answers `undefined`
941
+ for it. P belongs to the payee and its descriptor is a *refund* key from `provisionRefundKey`.
942
+ Wiring the claim helper to all three legs does not degrade gracefully: the salted arm derives
943
+ *some* P off the refund descriptor and the payment-hash check rejects it, so a correct record reads
944
+ as corrupt. That leg's reader is `rfqSignerOf`.
945
+ - **Non-hashlock corridors carry no `profile.hashlock` at all** — no `paymentHash`, no preimage
946
+ material, no placeholder; the key is simply absent, which is why `rfqSecretsProfile` takes the
947
+ payment hash as an optional second argument. They still write `profile.signer` if their leg is one
948
+ this wallet signs. The three corridors shipping today all lock to a preimage, but that is a fact
949
+ about them and not about RFQ. A corridor needing more than one descriptor — a co-signed leg, a
950
+ second key for an L1 half — extends `profile.signer` rather than fabricating a hashlock.
951
+ - **Both readers answer `undefined` only for "this corridor has no such half", and throw on a half
952
+ that is there and unusable.** Neither ever hands back a partial projection:
953
+ `preimageForSwapRecord` verifies only when the projection carries a `paymentHash`, so one missing
954
+ its hash would claim with an *unverified* preimage instead of failing. A thrown
955
+ `PreimageNotRecoverableError("malformed-record")` is a storage bug, not a protocol state — treating
956
+ it as "no preimage available" and falling back to a refund reads the two as the same thing.
957
+ - **An RFQ record stores no covenant.** The tree lives in the lockup's contract row, written before
958
+ the address could be funded and keyed by the script its params derive — a key `createContract`
959
+ refuses to write unless they reproduce it. So the rebuild takes the params from the caller:
960
+
961
+ ```ts
962
+ const params = await lockupContractParams(
963
+ await wallet.getContractManager(),
964
+ record.lockupAddress,
965
+ );
966
+ const swap = rebuildRfqSwap(record, params);
967
+ ```
968
+
969
+ `lockupContractParams` throws `LockupContractMissing` when this wallet has no row for the lockup —
970
+ a cleared contract store, or a record from elsewhere. A consumer that would rather not depend on
971
+ the contract store can keep its own copy of
972
+ `VHTLCV2ContractHandler.serializeParams(script.options)` and pass that instead; either way the
973
+ params are checked against the record's `lockupAddress` before a swap is handed back, so the wrong
974
+ row fails at restore rather than at refund time. **Superseded** for a consumer that wires
975
+ `RfqSwapManagerDeps.repository`: `restoreFromRepository()` is this loop, over every stored
976
+ record, with retention in front of it.
977
+
978
+ - **Pruning is the consumer's unless the manager holds the repository.** `shouldRetainRfqSwap(record,
979
+ now)` answers whether a record is still worth keeping — live swaps and `needs_counterparty`
980
+ always, terminal ones for `RFQ_SWAP_RETENTION_SECONDS` (30 days) after `updatedAt`. Sweep with it
981
+ at boot and pass the rejects to `removeRfqSwap`; skip it and a hot wallet's `rfqSwaps` store grows
982
+ without bound. `now` is **unix seconds**, the unit `RfqSwap.updatedAt` carries — `Date.now()` would
983
+ retire every terminal record after ~43 minutes. **Superseded** for a consumer that wires
984
+ `RfqSwapManagerDeps.repository`: `pruneRetiredSwaps()` is that sweep, and
985
+ `restoreFromRepository()` runs it first.
726
986
  - **A write that gates something irreversible throws; one that follows it does not.**
727
987
  `addAssetSwap` and `updateAssetSwap` throw on a failed read or write — nothing irreversible may
728
988
  happen until the record is durable, which is why `cancelOffer` writes its `cancelling` marker
@@ -752,4 +1012,5 @@ scanned? })` — the server key is required because a spend is classified by reb
752
1012
  receive swap monitored with nothing wired to claim it expires quietly, and a compile error is the
753
1013
  right way to learn a corridor was added. A caller with only send swaps can satisfy it with a stub
754
1014
  that throws. `RfqSwapActionName` gains `"claimLockup"`, so an exhaustive `switch` over it needs a
755
- new arm.
1015
+ new arm. **Superseded:** such a caller now installs `AvailableRfqSwapManagerCallbacks` and omits
1016
+ both — see above.
@@ -1,8 +1,9 @@
1
1
  // src/repository.ts
2
2
  var marketsCacheKey = (network, registry) => `arkade-intents-markets-${network}-${registry}`;
3
3
  var InMemoryAssetSwapRepository = class {
4
- version = 2;
4
+ version = 4;
5
5
  swaps = /* @__PURE__ */ new Map();
6
+ rfqSwaps = /* @__PURE__ */ new Map();
6
7
  scanned = /* @__PURE__ */ new Set();
7
8
  markets = /* @__PURE__ */ new Map();
8
9
  async saveSwap(swap) {
@@ -11,6 +12,18 @@ var InMemoryAssetSwapRepository = class {
11
12
  async getAllSwaps() {
12
13
  return [...this.swaps.values()];
13
14
  }
15
+ async saveRfqSwap(record) {
16
+ this.rfqSwaps.set(record.rfqId, record);
17
+ }
18
+ async getRfqSwap(rfqId) {
19
+ return this.rfqSwaps.get(rfqId);
20
+ }
21
+ async getAllRfqSwaps() {
22
+ return [...this.rfqSwaps.values()];
23
+ }
24
+ async removeRfqSwap(rfqId) {
25
+ this.rfqSwaps.delete(rfqId);
26
+ }
14
27
  async getScannedTxids() {
15
28
  return new Set(this.scanned);
16
29
  }
@@ -25,6 +38,7 @@ var InMemoryAssetSwapRepository = class {
25
38
  }
26
39
  async clear() {
27
40
  this.swaps.clear();
41
+ this.rfqSwaps.clear();
28
42
  this.scanned.clear();
29
43
  this.markets.clear();
30
44
  }