@arkade-os/swap 0.0.5 → 0.0.7
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 +79 -10
- package/dist/chunk-WGRU2DBF.js +38 -0
- package/dist/{chunk-Q4FAYBXS.js → chunk-ZDTRQZE2.js} +49 -15
- package/dist/index.cjs +103 -14
- package/dist/index.d.cts +46 -231
- package/dist/index.d.ts +46 -231
- package/dist/index.js +62 -35
- package/dist/nostr.cjs +15 -9
- package/dist/nostr.d.cts +4 -3
- package/dist/nostr.d.ts +4 -3
- package/dist/nostr.js +4 -11
- package/dist/repositories/realm/index.cjs +138 -0
- package/dist/repositories/realm/index.d.cts +103 -0
- package/dist/repositories/realm/index.d.ts +103 -0
- package/dist/repositories/realm/index.js +108 -0
- package/dist/repositories/sqlite/index.cjs +163 -0
- package/dist/repositories/sqlite/index.d.cts +63 -0
- package/dist/repositories/sqlite/index.d.ts +63 -0
- package/dist/repositories/sqlite/index.js +138 -0
- package/dist/repository-BwnZ8N62.d.cts +236 -0
- package/dist/repository-BwnZ8N62.d.ts +236 -0
- package/dist/{rfq-BH2yvo3O.d.cts → rfq-DfT9dAss.d.cts} +24 -11
- package/dist/{rfq-BH2yvo3O.d.ts → rfq-DfT9dAss.d.ts} +24 -11
- package/package.json +24 -4
package/dist/index.js
CHANGED
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
SWAP_LOCKUP_CONTRACT_LABEL,
|
|
23
23
|
SWAP_LOCKUP_CONTRACT_TYPE,
|
|
24
24
|
SwapRefusal,
|
|
25
|
+
arkadeAssetLeg,
|
|
25
26
|
arkadeSwapRequest,
|
|
26
27
|
assertFundable,
|
|
27
28
|
assertReceivable,
|
|
@@ -59,7 +60,11 @@ import {
|
|
|
59
60
|
unilateralRefundWithoutReceiverDelay,
|
|
60
61
|
verifyLockupAddress,
|
|
61
62
|
verifyReceiveInvoice
|
|
62
|
-
} from "./chunk-
|
|
63
|
+
} from "./chunk-ZDTRQZE2.js";
|
|
64
|
+
import {
|
|
65
|
+
InMemoryAssetSwapRepository,
|
|
66
|
+
marketsCacheKey
|
|
67
|
+
} from "./chunk-WGRU2DBF.js";
|
|
63
68
|
|
|
64
69
|
// src/offer.ts
|
|
65
70
|
import { hex as hex2 } from "@scure/base";
|
|
@@ -690,40 +695,6 @@ var validatePlan = (plan, giveBalance, dust) => {
|
|
|
690
695
|
return void 0;
|
|
691
696
|
};
|
|
692
697
|
|
|
693
|
-
// src/repository.ts
|
|
694
|
-
var marketsCacheKey = (network, registry) => `arkade-intents-markets-${network}-${registry}`;
|
|
695
|
-
var InMemoryAssetSwapRepository = class {
|
|
696
|
-
version = 2;
|
|
697
|
-
swaps = /* @__PURE__ */ new Map();
|
|
698
|
-
scanned = /* @__PURE__ */ new Set();
|
|
699
|
-
markets = /* @__PURE__ */ new Map();
|
|
700
|
-
async saveSwap(swap) {
|
|
701
|
-
this.swaps.set(swap.id, swap);
|
|
702
|
-
}
|
|
703
|
-
async getAllSwaps() {
|
|
704
|
-
return [...this.swaps.values()];
|
|
705
|
-
}
|
|
706
|
-
async getScannedTxids() {
|
|
707
|
-
return new Set(this.scanned);
|
|
708
|
-
}
|
|
709
|
-
async markTxidsScanned(txids) {
|
|
710
|
-
for (const txid of txids) this.scanned.add(txid);
|
|
711
|
-
}
|
|
712
|
-
async getCachedMarkets(network, registry) {
|
|
713
|
-
return this.markets.get(marketsCacheKey(network, registry));
|
|
714
|
-
}
|
|
715
|
-
async saveCachedMarkets(network, registry, entry) {
|
|
716
|
-
this.markets.set(marketsCacheKey(network, registry), entry);
|
|
717
|
-
}
|
|
718
|
-
async clear() {
|
|
719
|
-
this.swaps.clear();
|
|
720
|
-
this.scanned.clear();
|
|
721
|
-
this.markets.clear();
|
|
722
|
-
}
|
|
723
|
-
async [Symbol.asyncDispose]() {
|
|
724
|
-
}
|
|
725
|
-
};
|
|
726
|
-
|
|
727
698
|
// src/indexedDbRepository.ts
|
|
728
699
|
import { closeDatabase, openDatabase } from "@arkade-os/sdk";
|
|
729
700
|
var DEFAULT_DB_NAME = "arkade-intents";
|
|
@@ -2207,6 +2178,60 @@ var outcomeOf = (swap) => {
|
|
|
2207
2178
|
};
|
|
2208
2179
|
var errorMessage = (error) => error instanceof Error ? error.message : String(error);
|
|
2209
2180
|
var outpointKey = (vtxo) => `${vtxo.txid}:${vtxo.vout}`;
|
|
2181
|
+
|
|
2182
|
+
// src/activity.ts
|
|
2183
|
+
var LABELS = {
|
|
2184
|
+
lightning_send: "Lightning send",
|
|
2185
|
+
lightning_receive: "Lightning receive",
|
|
2186
|
+
onchain_send: "Onchain send"
|
|
2187
|
+
};
|
|
2188
|
+
var OUTCOME = {
|
|
2189
|
+
pending: "pending",
|
|
2190
|
+
// `claimable` and `claimed` are both in-progress states with no
|
|
2191
|
+
// user-visible phase distinct from "pending". `needs_counterparty` is
|
|
2192
|
+
// different in kind — the swap is BLOCKED, not merely in flight, since no
|
|
2193
|
+
// unilateral trader move exists (see `RfqSwapState`). Collapsing it into
|
|
2194
|
+
// `pending` here is a deliberate choice the opaque-token design permits —
|
|
2195
|
+
// apps map tokens themselves — but a future reader weighing a `"blocked"`
|
|
2196
|
+
// or `"stuck"` token should know this was already considered.
|
|
2197
|
+
claimable: "pending",
|
|
2198
|
+
claimed: "pending",
|
|
2199
|
+
needs_counterparty: "pending",
|
|
2200
|
+
settled: "settled",
|
|
2201
|
+
refunded: "refunded",
|
|
2202
|
+
failed: "failed"
|
|
2203
|
+
};
|
|
2204
|
+
function swapActivityResolver(deps) {
|
|
2205
|
+
let byTxid = /* @__PURE__ */ new Map();
|
|
2206
|
+
return {
|
|
2207
|
+
id: "arkade:swap",
|
|
2208
|
+
async prepare() {
|
|
2209
|
+
const swaps = await deps.listSwaps();
|
|
2210
|
+
const index = /* @__PURE__ */ new Map();
|
|
2211
|
+
for (const swap of swaps) {
|
|
2212
|
+
for (const txid of swap.txids) {
|
|
2213
|
+
if (txid) index.set(txid, swap);
|
|
2214
|
+
}
|
|
2215
|
+
}
|
|
2216
|
+
byTxid = index;
|
|
2217
|
+
},
|
|
2218
|
+
resolve(tx) {
|
|
2219
|
+
const key = tx.key.arkTxid || tx.key.commitmentTxid || tx.key.boardingTxid;
|
|
2220
|
+
const swap = key ? byTxid.get(key) : void 0;
|
|
2221
|
+
if (!swap) return void 0;
|
|
2222
|
+
const lostReceive = swap.kind === "lightning_receive" && swap.state === "refunded";
|
|
2223
|
+
return [
|
|
2224
|
+
{
|
|
2225
|
+
groupId: `swap:${swap.rfqId}`,
|
|
2226
|
+
label: LABELS[swap.kind],
|
|
2227
|
+
kind: "swap",
|
|
2228
|
+
outcome: lostReceive ? "lost" : OUTCOME[swap.state],
|
|
2229
|
+
metadata: { rfqId: swap.rfqId, swapKind: swap.kind }
|
|
2230
|
+
}
|
|
2231
|
+
];
|
|
2232
|
+
}
|
|
2233
|
+
};
|
|
2234
|
+
}
|
|
2210
2235
|
export {
|
|
2211
2236
|
ARKADE_ASSET,
|
|
2212
2237
|
ARKADE_BTC,
|
|
@@ -2245,6 +2270,7 @@ export {
|
|
|
2245
2270
|
SWAP_LOCKUP_CONTRACT_TYPE,
|
|
2246
2271
|
SwapRefusal,
|
|
2247
2272
|
addAssetSwap,
|
|
2273
|
+
arkadeAssetLeg,
|
|
2248
2274
|
arkadeSwapRequest,
|
|
2249
2275
|
assertFundable,
|
|
2250
2276
|
assertReceivable,
|
|
@@ -2306,6 +2332,7 @@ export {
|
|
|
2306
2332
|
senderIdentityForSwapRecord,
|
|
2307
2333
|
spendTxidsOf,
|
|
2308
2334
|
spendUpdate,
|
|
2335
|
+
swapActivityResolver,
|
|
2309
2336
|
swapPrograms,
|
|
2310
2337
|
swapSecretsToRecord,
|
|
2311
2338
|
unilateralClaimDelay,
|
package/dist/nostr.cjs
CHANGED
|
@@ -91,6 +91,20 @@ var SwapRefusal = class extends Error {
|
|
|
91
91
|
}
|
|
92
92
|
};
|
|
93
93
|
var MIN_HEADROOM_SECONDS = 90 * 60;
|
|
94
|
+
var expectQuote = (payload, rfqId, requestedPair) => {
|
|
95
|
+
const p = payload;
|
|
96
|
+
if (p?.type === "rfq_refusal") throw new SwapRefusal(p.reason ?? "unknown", p.rfq_id ?? rfqId);
|
|
97
|
+
if (p?.type !== "rfq_quote" || p.rfq_id !== rfqId) {
|
|
98
|
+
throw new Error(`unexpected reply: ${p?.type ?? "no payload"}`);
|
|
99
|
+
}
|
|
100
|
+
if (requestedPair !== void 0 && p.pair !== requestedPair) {
|
|
101
|
+
throw new Error(
|
|
102
|
+
`solver quoted ${JSON.stringify(p.pair)}, not the requested ${requestedPair}`
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
return payload;
|
|
106
|
+
};
|
|
107
|
+
var pairOf = (payload) => typeof payload.pair === "string" ? payload.pair : void 0;
|
|
94
108
|
var SEQUENCE_GRANULARITY_SECONDS = 512;
|
|
95
109
|
var SOLO_REFUND_HEADROOM_SECONDS = 8 * SEQUENCE_GRANULARITY_SECONDS;
|
|
96
110
|
var MIN_CLAIM_WINDOW_SECONDS = 30 * 60;
|
|
@@ -119,14 +133,6 @@ var closeReasons = (raw) => raw.map((entry) => {
|
|
|
119
133
|
const { url, reason } = entry ?? {};
|
|
120
134
|
return url ? `${url}: ${reason ?? "closed"}` : reason ?? "closed";
|
|
121
135
|
});
|
|
122
|
-
var asQuote = (payload, rfqId) => {
|
|
123
|
-
const p = payload;
|
|
124
|
-
if (p?.type === "rfq_refusal") throw new SwapRefusal(p.reason ?? "unknown", p.rfq_id ?? rfqId);
|
|
125
|
-
if (p?.type !== "rfq_quote" || p.rfq_id !== rfqId) {
|
|
126
|
-
throw new Error(`unexpected reply: ${p?.type ?? "no payload"}`);
|
|
127
|
-
}
|
|
128
|
-
return payload;
|
|
129
|
-
};
|
|
130
136
|
var nostrRfqTransport = (options) => {
|
|
131
137
|
const relays = options.relays;
|
|
132
138
|
const solverPubkey = options.solverPubkey;
|
|
@@ -202,7 +208,7 @@ var nostrRfqTransport = (options) => {
|
|
|
202
208
|
const rfqId = String(payload.rfq_id);
|
|
203
209
|
const reply = awaitReply(rfqId);
|
|
204
210
|
await send(payload);
|
|
205
|
-
return
|
|
211
|
+
return expectQuote(await reply, rfqId, pairOf(payload));
|
|
206
212
|
},
|
|
207
213
|
async status(rfqId) {
|
|
208
214
|
const reply = awaitReply(rfqId);
|
package/dist/nostr.d.cts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { a as RfqTransport } from './rfq-
|
|
1
|
+
import { a as RfqTransport } from './rfq-DfT9dAss.cjs';
|
|
2
2
|
import { SimplePool } from 'nostr-tools';
|
|
3
3
|
import '@arkade-os/sdk';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* The Nostr RFQ transport — the PRODUCTION one (
|
|
7
|
-
*
|
|
6
|
+
* The Nostr RFQ transport — the PRODUCTION one (the kind, the NIP-44 framing
|
|
7
|
+
* and the payloads it carries are public at
|
|
8
|
+
* https://docs.arkadeos.com/intents/reference/rfq).
|
|
8
9
|
*
|
|
9
10
|
* `rfq.ts` ships two other transports: `httpTransport`, and `relayTransport`
|
|
10
11
|
* which speaks the dev broker's `{op:"sub"|"event"}` framing. Neither is what a
|
package/dist/nostr.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { a as RfqTransport } from './rfq-
|
|
1
|
+
import { a as RfqTransport } from './rfq-DfT9dAss.js';
|
|
2
2
|
import { SimplePool } from 'nostr-tools';
|
|
3
3
|
import '@arkade-os/sdk';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* The Nostr RFQ transport — the PRODUCTION one (
|
|
7
|
-
*
|
|
6
|
+
* The Nostr RFQ transport — the PRODUCTION one (the kind, the NIP-44 framing
|
|
7
|
+
* and the payloads it carries are public at
|
|
8
|
+
* https://docs.arkadeos.com/intents/reference/rfq).
|
|
8
9
|
*
|
|
9
10
|
* `rfq.ts` ships two other transports: `httpTransport`, and `relayTransport`
|
|
10
11
|
* which speaks the dev broker's `{op:"sub"|"event"}` framing. Neither is what a
|
package/dist/nostr.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
expectQuote,
|
|
3
|
+
pairOf
|
|
4
|
+
} from "./chunk-ZDTRQZE2.js";
|
|
4
5
|
|
|
5
6
|
// src/nostr.ts
|
|
6
7
|
import {
|
|
@@ -32,14 +33,6 @@ var closeReasons = (raw) => raw.map((entry) => {
|
|
|
32
33
|
const { url, reason } = entry ?? {};
|
|
33
34
|
return url ? `${url}: ${reason ?? "closed"}` : reason ?? "closed";
|
|
34
35
|
});
|
|
35
|
-
var asQuote = (payload, rfqId) => {
|
|
36
|
-
const p = payload;
|
|
37
|
-
if (p?.type === "rfq_refusal") throw new SwapRefusal(p.reason ?? "unknown", p.rfq_id ?? rfqId);
|
|
38
|
-
if (p?.type !== "rfq_quote" || p.rfq_id !== rfqId) {
|
|
39
|
-
throw new Error(`unexpected reply: ${p?.type ?? "no payload"}`);
|
|
40
|
-
}
|
|
41
|
-
return payload;
|
|
42
|
-
};
|
|
43
36
|
var nostrRfqTransport = (options) => {
|
|
44
37
|
const relays = options.relays;
|
|
45
38
|
const solverPubkey = options.solverPubkey;
|
|
@@ -115,7 +108,7 @@ var nostrRfqTransport = (options) => {
|
|
|
115
108
|
const rfqId = String(payload.rfq_id);
|
|
116
109
|
const reply = awaitReply(rfqId);
|
|
117
110
|
await send(payload);
|
|
118
|
-
return
|
|
111
|
+
return expectQuote(await reply, rfqId, pairOf(payload));
|
|
119
112
|
},
|
|
120
113
|
async status(rfqId) {
|
|
121
114
|
const reply = awaitReply(rfqId);
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/repositories/realm/index.ts
|
|
21
|
+
var realm_exports = {};
|
|
22
|
+
__export(realm_exports, {
|
|
23
|
+
ArkadeAssetSwapMarketsCacheSchema: () => ArkadeAssetSwapMarketsCacheSchema,
|
|
24
|
+
ArkadeAssetSwapScannedTxidSchema: () => ArkadeAssetSwapScannedTxidSchema,
|
|
25
|
+
ArkadeAssetSwapSchema: () => ArkadeAssetSwapSchema,
|
|
26
|
+
AssetSwapRealmSchemas: () => AssetSwapRealmSchemas,
|
|
27
|
+
RealmAssetSwapRepository: () => RealmAssetSwapRepository
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(realm_exports);
|
|
30
|
+
|
|
31
|
+
// src/repository.ts
|
|
32
|
+
var marketsCacheKey = (network, registry) => `arkade-intents-markets-${network}-${registry}`;
|
|
33
|
+
|
|
34
|
+
// src/repositories/realm/repository.ts
|
|
35
|
+
var SWAPS = "ArkadeAssetSwap";
|
|
36
|
+
var SCANNED = "ArkadeAssetSwapScannedTxid";
|
|
37
|
+
var MARKETS = "ArkadeAssetSwapMarketsCache";
|
|
38
|
+
var RealmAssetSwapRepository = class {
|
|
39
|
+
constructor(realm) {
|
|
40
|
+
this.realm = realm;
|
|
41
|
+
}
|
|
42
|
+
realm;
|
|
43
|
+
version = 2;
|
|
44
|
+
async saveSwap(swap) {
|
|
45
|
+
this.realm.write(() => {
|
|
46
|
+
this.realm.create(
|
|
47
|
+
SWAPS,
|
|
48
|
+
{
|
|
49
|
+
id: swap.id,
|
|
50
|
+
status: swap.status,
|
|
51
|
+
createdAt: swap.createdAt,
|
|
52
|
+
data: JSON.stringify(swap)
|
|
53
|
+
},
|
|
54
|
+
"modified"
|
|
55
|
+
);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
async getAllSwaps() {
|
|
59
|
+
return [...this.realm.objects(SWAPS)].map(
|
|
60
|
+
(o) => JSON.parse(o.data)
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
async getScannedTxids() {
|
|
64
|
+
return new Set([...this.realm.objects(SCANNED)].map((o) => o.txid));
|
|
65
|
+
}
|
|
66
|
+
async markTxidsScanned(txids) {
|
|
67
|
+
this.realm.write(() => {
|
|
68
|
+
for (const txid of txids) this.realm.create(SCANNED, { txid }, "modified");
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
async getCachedMarkets(network, registry) {
|
|
72
|
+
const [row] = [
|
|
73
|
+
...this.realm.objects(MARKETS).filtered("key == $0", marketsCacheKey(network, registry))
|
|
74
|
+
];
|
|
75
|
+
return row ? JSON.parse(row.data) : void 0;
|
|
76
|
+
}
|
|
77
|
+
async saveCachedMarkets(network, registry, entry) {
|
|
78
|
+
this.realm.write(() => {
|
|
79
|
+
this.realm.create(
|
|
80
|
+
MARKETS,
|
|
81
|
+
{ key: marketsCacheKey(network, registry), data: JSON.stringify(entry) },
|
|
82
|
+
"modified"
|
|
83
|
+
);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
/** All three schemas in one write: clearing swaps but keeping scanned txids
|
|
87
|
+
* would leave the restore scan permanently skipping those funding txs, so
|
|
88
|
+
* a partial clear must not be observable. */
|
|
89
|
+
async clear() {
|
|
90
|
+
this.realm.write(() => {
|
|
91
|
+
for (const name of [SWAPS, SCANNED, MARKETS]) {
|
|
92
|
+
this.realm.delete(this.realm.objects(name));
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
async [Symbol.asyncDispose]() {
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
// src/repositories/realm/schemas.ts
|
|
101
|
+
var ArkadeAssetSwapSchema = {
|
|
102
|
+
name: "ArkadeAssetSwap",
|
|
103
|
+
primaryKey: "id",
|
|
104
|
+
properties: {
|
|
105
|
+
id: "string",
|
|
106
|
+
status: "string",
|
|
107
|
+
createdAt: "int",
|
|
108
|
+
data: "string"
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
var ArkadeAssetSwapScannedTxidSchema = {
|
|
112
|
+
name: "ArkadeAssetSwapScannedTxid",
|
|
113
|
+
primaryKey: "txid",
|
|
114
|
+
properties: {
|
|
115
|
+
txid: "string"
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
var ArkadeAssetSwapMarketsCacheSchema = {
|
|
119
|
+
name: "ArkadeAssetSwapMarketsCache",
|
|
120
|
+
primaryKey: "key",
|
|
121
|
+
properties: {
|
|
122
|
+
key: "string",
|
|
123
|
+
data: "string"
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
var AssetSwapRealmSchemas = [
|
|
127
|
+
ArkadeAssetSwapSchema,
|
|
128
|
+
ArkadeAssetSwapScannedTxidSchema,
|
|
129
|
+
ArkadeAssetSwapMarketsCacheSchema
|
|
130
|
+
];
|
|
131
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
132
|
+
0 && (module.exports = {
|
|
133
|
+
ArkadeAssetSwapMarketsCacheSchema,
|
|
134
|
+
ArkadeAssetSwapScannedTxidSchema,
|
|
135
|
+
ArkadeAssetSwapSchema,
|
|
136
|
+
AssetSwapRealmSchemas,
|
|
137
|
+
RealmAssetSwapRepository
|
|
138
|
+
});
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { RealmLike } from '@arkade-os/sdk/repositories/realm';
|
|
2
|
+
import { A as AssetSwapRepository, a as AssetSwap, M as MarketsCacheEntry } from '../../repository-BwnZ8N62.cjs';
|
|
3
|
+
import '@arkade-os/solver-discovery';
|
|
4
|
+
import '@arkade-os/sdk';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Realm backend for React Native.
|
|
8
|
+
*
|
|
9
|
+
* `realm` is not a dependency of this package: consumers open Realm with the
|
|
10
|
+
* schemas from `./schemas.ts` and pass the instance, validated against the
|
|
11
|
+
* shared `RealmLike` shape from `@arkade-os/sdk`.
|
|
12
|
+
*
|
|
13
|
+
* **Records are serialized as JSON**, whole, into a `data` property —
|
|
14
|
+
* `status` and `createdAt` are mapped out for querying only, so no field of a
|
|
15
|
+
* record can be dropped. That holds for JSON-safe values: a consumer-added
|
|
16
|
+
* `Date` comes back a string and a `bigint` throws on save, unlike the
|
|
17
|
+
* IndexedDB backend's structured clone. `AssetSwap` itself is JSON-safe by
|
|
18
|
+
* design.
|
|
19
|
+
*
|
|
20
|
+
* Realm creates the schemas on open, so there is nothing to initialise. The
|
|
21
|
+
* consumer owns the Realm lifecycle — `[Symbol.asyncDispose]` is a no-op.
|
|
22
|
+
*/
|
|
23
|
+
declare class RealmAssetSwapRepository implements AssetSwapRepository {
|
|
24
|
+
private readonly realm;
|
|
25
|
+
readonly version: 2;
|
|
26
|
+
constructor(realm: RealmLike);
|
|
27
|
+
saveSwap(swap: AssetSwap): Promise<void>;
|
|
28
|
+
getAllSwaps(): Promise<AssetSwap[]>;
|
|
29
|
+
getScannedTxids(): Promise<Set<string>>;
|
|
30
|
+
markTxidsScanned(txids: Iterable<string>): Promise<void>;
|
|
31
|
+
getCachedMarkets(network: string, registry: string): Promise<MarketsCacheEntry | undefined>;
|
|
32
|
+
saveCachedMarkets(network: string, registry: string, entry: MarketsCacheEntry): Promise<void>;
|
|
33
|
+
/** All three schemas in one write: clearing swaps but keeping scanned txids
|
|
34
|
+
* would leave the restore scan permanently skipping those funding txs, so
|
|
35
|
+
* a partial clear must not be observable. */
|
|
36
|
+
clear(): Promise<void>;
|
|
37
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Realm object schemas for the asset-swap repository.
|
|
42
|
+
*
|
|
43
|
+
* The names land in the **consuming application's** schema namespace, next to
|
|
44
|
+
* its own models and the SDK's `Ark*` / the Boltz plugin's `Boltz*`, so they
|
|
45
|
+
* are prefixed with `ArkadeAssetSwap`. Unlike the SQLite backend there is no
|
|
46
|
+
* prefix option: a Realm schema name is baked into the schema objects the
|
|
47
|
+
* consumer registers and into every `realm.objects(…)` call here.
|
|
48
|
+
*
|
|
49
|
+
* Since `realm` is not a dependency of this package, schemas are plain JS
|
|
50
|
+
* objects conforming to Realm's ObjectSchema shape. They are new, so a consumer
|
|
51
|
+
* adds them to its Realm config and bumps its own `schemaVersion`; no migration
|
|
52
|
+
* helper ships here.
|
|
53
|
+
*/
|
|
54
|
+
declare const ArkadeAssetSwapSchema: {
|
|
55
|
+
name: string;
|
|
56
|
+
primaryKey: string;
|
|
57
|
+
properties: {
|
|
58
|
+
id: string;
|
|
59
|
+
status: string;
|
|
60
|
+
createdAt: string;
|
|
61
|
+
data: string;
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
declare const ArkadeAssetSwapScannedTxidSchema: {
|
|
65
|
+
name: string;
|
|
66
|
+
primaryKey: string;
|
|
67
|
+
properties: {
|
|
68
|
+
txid: string;
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
declare const ArkadeAssetSwapMarketsCacheSchema: {
|
|
72
|
+
name: string;
|
|
73
|
+
primaryKey: string;
|
|
74
|
+
properties: {
|
|
75
|
+
key: string;
|
|
76
|
+
data: string;
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
declare const AssetSwapRealmSchemas: ({
|
|
80
|
+
name: string;
|
|
81
|
+
primaryKey: string;
|
|
82
|
+
properties: {
|
|
83
|
+
id: string;
|
|
84
|
+
status: string;
|
|
85
|
+
createdAt: string;
|
|
86
|
+
data: string;
|
|
87
|
+
};
|
|
88
|
+
} | {
|
|
89
|
+
name: string;
|
|
90
|
+
primaryKey: string;
|
|
91
|
+
properties: {
|
|
92
|
+
txid: string;
|
|
93
|
+
};
|
|
94
|
+
} | {
|
|
95
|
+
name: string;
|
|
96
|
+
primaryKey: string;
|
|
97
|
+
properties: {
|
|
98
|
+
key: string;
|
|
99
|
+
data: string;
|
|
100
|
+
};
|
|
101
|
+
})[];
|
|
102
|
+
|
|
103
|
+
export { ArkadeAssetSwapMarketsCacheSchema, ArkadeAssetSwapScannedTxidSchema, ArkadeAssetSwapSchema, AssetSwapRealmSchemas, RealmAssetSwapRepository };
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { RealmLike } from '@arkade-os/sdk/repositories/realm';
|
|
2
|
+
import { A as AssetSwapRepository, a as AssetSwap, M as MarketsCacheEntry } from '../../repository-BwnZ8N62.js';
|
|
3
|
+
import '@arkade-os/solver-discovery';
|
|
4
|
+
import '@arkade-os/sdk';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Realm backend for React Native.
|
|
8
|
+
*
|
|
9
|
+
* `realm` is not a dependency of this package: consumers open Realm with the
|
|
10
|
+
* schemas from `./schemas.ts` and pass the instance, validated against the
|
|
11
|
+
* shared `RealmLike` shape from `@arkade-os/sdk`.
|
|
12
|
+
*
|
|
13
|
+
* **Records are serialized as JSON**, whole, into a `data` property —
|
|
14
|
+
* `status` and `createdAt` are mapped out for querying only, so no field of a
|
|
15
|
+
* record can be dropped. That holds for JSON-safe values: a consumer-added
|
|
16
|
+
* `Date` comes back a string and a `bigint` throws on save, unlike the
|
|
17
|
+
* IndexedDB backend's structured clone. `AssetSwap` itself is JSON-safe by
|
|
18
|
+
* design.
|
|
19
|
+
*
|
|
20
|
+
* Realm creates the schemas on open, so there is nothing to initialise. The
|
|
21
|
+
* consumer owns the Realm lifecycle — `[Symbol.asyncDispose]` is a no-op.
|
|
22
|
+
*/
|
|
23
|
+
declare class RealmAssetSwapRepository implements AssetSwapRepository {
|
|
24
|
+
private readonly realm;
|
|
25
|
+
readonly version: 2;
|
|
26
|
+
constructor(realm: RealmLike);
|
|
27
|
+
saveSwap(swap: AssetSwap): Promise<void>;
|
|
28
|
+
getAllSwaps(): Promise<AssetSwap[]>;
|
|
29
|
+
getScannedTxids(): Promise<Set<string>>;
|
|
30
|
+
markTxidsScanned(txids: Iterable<string>): Promise<void>;
|
|
31
|
+
getCachedMarkets(network: string, registry: string): Promise<MarketsCacheEntry | undefined>;
|
|
32
|
+
saveCachedMarkets(network: string, registry: string, entry: MarketsCacheEntry): Promise<void>;
|
|
33
|
+
/** All three schemas in one write: clearing swaps but keeping scanned txids
|
|
34
|
+
* would leave the restore scan permanently skipping those funding txs, so
|
|
35
|
+
* a partial clear must not be observable. */
|
|
36
|
+
clear(): Promise<void>;
|
|
37
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Realm object schemas for the asset-swap repository.
|
|
42
|
+
*
|
|
43
|
+
* The names land in the **consuming application's** schema namespace, next to
|
|
44
|
+
* its own models and the SDK's `Ark*` / the Boltz plugin's `Boltz*`, so they
|
|
45
|
+
* are prefixed with `ArkadeAssetSwap`. Unlike the SQLite backend there is no
|
|
46
|
+
* prefix option: a Realm schema name is baked into the schema objects the
|
|
47
|
+
* consumer registers and into every `realm.objects(…)` call here.
|
|
48
|
+
*
|
|
49
|
+
* Since `realm` is not a dependency of this package, schemas are plain JS
|
|
50
|
+
* objects conforming to Realm's ObjectSchema shape. They are new, so a consumer
|
|
51
|
+
* adds them to its Realm config and bumps its own `schemaVersion`; no migration
|
|
52
|
+
* helper ships here.
|
|
53
|
+
*/
|
|
54
|
+
declare const ArkadeAssetSwapSchema: {
|
|
55
|
+
name: string;
|
|
56
|
+
primaryKey: string;
|
|
57
|
+
properties: {
|
|
58
|
+
id: string;
|
|
59
|
+
status: string;
|
|
60
|
+
createdAt: string;
|
|
61
|
+
data: string;
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
declare const ArkadeAssetSwapScannedTxidSchema: {
|
|
65
|
+
name: string;
|
|
66
|
+
primaryKey: string;
|
|
67
|
+
properties: {
|
|
68
|
+
txid: string;
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
declare const ArkadeAssetSwapMarketsCacheSchema: {
|
|
72
|
+
name: string;
|
|
73
|
+
primaryKey: string;
|
|
74
|
+
properties: {
|
|
75
|
+
key: string;
|
|
76
|
+
data: string;
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
declare const AssetSwapRealmSchemas: ({
|
|
80
|
+
name: string;
|
|
81
|
+
primaryKey: string;
|
|
82
|
+
properties: {
|
|
83
|
+
id: string;
|
|
84
|
+
status: string;
|
|
85
|
+
createdAt: string;
|
|
86
|
+
data: string;
|
|
87
|
+
};
|
|
88
|
+
} | {
|
|
89
|
+
name: string;
|
|
90
|
+
primaryKey: string;
|
|
91
|
+
properties: {
|
|
92
|
+
txid: string;
|
|
93
|
+
};
|
|
94
|
+
} | {
|
|
95
|
+
name: string;
|
|
96
|
+
primaryKey: string;
|
|
97
|
+
properties: {
|
|
98
|
+
key: string;
|
|
99
|
+
data: string;
|
|
100
|
+
};
|
|
101
|
+
})[];
|
|
102
|
+
|
|
103
|
+
export { ArkadeAssetSwapMarketsCacheSchema, ArkadeAssetSwapScannedTxidSchema, ArkadeAssetSwapSchema, AssetSwapRealmSchemas, RealmAssetSwapRepository };
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import {
|
|
2
|
+
marketsCacheKey
|
|
3
|
+
} from "../../chunk-WGRU2DBF.js";
|
|
4
|
+
|
|
5
|
+
// src/repositories/realm/repository.ts
|
|
6
|
+
var SWAPS = "ArkadeAssetSwap";
|
|
7
|
+
var SCANNED = "ArkadeAssetSwapScannedTxid";
|
|
8
|
+
var MARKETS = "ArkadeAssetSwapMarketsCache";
|
|
9
|
+
var RealmAssetSwapRepository = class {
|
|
10
|
+
constructor(realm) {
|
|
11
|
+
this.realm = realm;
|
|
12
|
+
}
|
|
13
|
+
realm;
|
|
14
|
+
version = 2;
|
|
15
|
+
async saveSwap(swap) {
|
|
16
|
+
this.realm.write(() => {
|
|
17
|
+
this.realm.create(
|
|
18
|
+
SWAPS,
|
|
19
|
+
{
|
|
20
|
+
id: swap.id,
|
|
21
|
+
status: swap.status,
|
|
22
|
+
createdAt: swap.createdAt,
|
|
23
|
+
data: JSON.stringify(swap)
|
|
24
|
+
},
|
|
25
|
+
"modified"
|
|
26
|
+
);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
async getAllSwaps() {
|
|
30
|
+
return [...this.realm.objects(SWAPS)].map(
|
|
31
|
+
(o) => JSON.parse(o.data)
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
async getScannedTxids() {
|
|
35
|
+
return new Set([...this.realm.objects(SCANNED)].map((o) => o.txid));
|
|
36
|
+
}
|
|
37
|
+
async markTxidsScanned(txids) {
|
|
38
|
+
this.realm.write(() => {
|
|
39
|
+
for (const txid of txids) this.realm.create(SCANNED, { txid }, "modified");
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
async getCachedMarkets(network, registry) {
|
|
43
|
+
const [row] = [
|
|
44
|
+
...this.realm.objects(MARKETS).filtered("key == $0", marketsCacheKey(network, registry))
|
|
45
|
+
];
|
|
46
|
+
return row ? JSON.parse(row.data) : void 0;
|
|
47
|
+
}
|
|
48
|
+
async saveCachedMarkets(network, registry, entry) {
|
|
49
|
+
this.realm.write(() => {
|
|
50
|
+
this.realm.create(
|
|
51
|
+
MARKETS,
|
|
52
|
+
{ key: marketsCacheKey(network, registry), data: JSON.stringify(entry) },
|
|
53
|
+
"modified"
|
|
54
|
+
);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/** All three schemas in one write: clearing swaps but keeping scanned txids
|
|
58
|
+
* would leave the restore scan permanently skipping those funding txs, so
|
|
59
|
+
* a partial clear must not be observable. */
|
|
60
|
+
async clear() {
|
|
61
|
+
this.realm.write(() => {
|
|
62
|
+
for (const name of [SWAPS, SCANNED, MARKETS]) {
|
|
63
|
+
this.realm.delete(this.realm.objects(name));
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
async [Symbol.asyncDispose]() {
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// src/repositories/realm/schemas.ts
|
|
72
|
+
var ArkadeAssetSwapSchema = {
|
|
73
|
+
name: "ArkadeAssetSwap",
|
|
74
|
+
primaryKey: "id",
|
|
75
|
+
properties: {
|
|
76
|
+
id: "string",
|
|
77
|
+
status: "string",
|
|
78
|
+
createdAt: "int",
|
|
79
|
+
data: "string"
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
var ArkadeAssetSwapScannedTxidSchema = {
|
|
83
|
+
name: "ArkadeAssetSwapScannedTxid",
|
|
84
|
+
primaryKey: "txid",
|
|
85
|
+
properties: {
|
|
86
|
+
txid: "string"
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
var ArkadeAssetSwapMarketsCacheSchema = {
|
|
90
|
+
name: "ArkadeAssetSwapMarketsCache",
|
|
91
|
+
primaryKey: "key",
|
|
92
|
+
properties: {
|
|
93
|
+
key: "string",
|
|
94
|
+
data: "string"
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
var AssetSwapRealmSchemas = [
|
|
98
|
+
ArkadeAssetSwapSchema,
|
|
99
|
+
ArkadeAssetSwapScannedTxidSchema,
|
|
100
|
+
ArkadeAssetSwapMarketsCacheSchema
|
|
101
|
+
];
|
|
102
|
+
export {
|
|
103
|
+
ArkadeAssetSwapMarketsCacheSchema,
|
|
104
|
+
ArkadeAssetSwapScannedTxidSchema,
|
|
105
|
+
ArkadeAssetSwapSchema,
|
|
106
|
+
AssetSwapRealmSchemas,
|
|
107
|
+
RealmAssetSwapRepository
|
|
108
|
+
};
|