@arkade-os/sdk 0.4.0-next.0 → 0.4.0-next.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +127 -24
- package/dist/cjs/bip322/index.js +270 -0
- package/dist/cjs/index.js +4 -2
- package/dist/cjs/intent/index.js +19 -9
- package/dist/cjs/repositories/indexedDB/contractRepository.js +1 -1
- package/dist/cjs/repositories/indexedDB/db.js +8 -46
- package/dist/cjs/repositories/indexedDB/walletRepository.js +1 -1
- package/dist/cjs/repositories/realm/contractRepository.js +120 -0
- package/dist/cjs/repositories/realm/index.js +9 -0
- package/dist/cjs/repositories/realm/schemas.js +108 -0
- package/dist/cjs/repositories/realm/types.js +7 -0
- package/dist/cjs/repositories/realm/walletRepository.js +273 -0
- package/dist/cjs/repositories/serialization.js +49 -0
- package/dist/cjs/repositories/sqlite/contractRepository.js +139 -0
- package/dist/cjs/repositories/sqlite/index.js +7 -0
- package/dist/cjs/repositories/sqlite/types.js +2 -0
- package/dist/cjs/repositories/sqlite/walletRepository.js +328 -0
- package/dist/cjs/wallet/serviceWorker/wallet.js +9 -1
- package/dist/cjs/wallet/vtxo-manager.js +7 -0
- package/dist/cjs/worker/messageBus.js +22 -2
- package/dist/esm/bip322/index.js +267 -0
- package/dist/esm/index.js +4 -1
- package/dist/esm/intent/index.js +16 -7
- package/dist/esm/repositories/indexedDB/contractRepository.js +1 -1
- package/dist/esm/repositories/indexedDB/db.js +2 -40
- package/dist/esm/repositories/indexedDB/walletRepository.js +1 -1
- package/dist/esm/repositories/realm/contractRepository.js +116 -0
- package/dist/esm/repositories/realm/index.js +3 -0
- package/dist/esm/repositories/realm/schemas.js +105 -0
- package/dist/esm/repositories/realm/types.js +6 -0
- package/dist/esm/repositories/realm/walletRepository.js +269 -0
- package/dist/esm/repositories/serialization.js +40 -0
- package/dist/esm/repositories/sqlite/contractRepository.js +135 -0
- package/dist/esm/repositories/sqlite/index.js +2 -0
- package/dist/esm/repositories/sqlite/types.js +1 -0
- package/dist/esm/repositories/sqlite/walletRepository.js +324 -0
- package/dist/esm/wallet/serviceWorker/wallet.js +9 -1
- package/dist/esm/wallet/vtxo-manager.js +7 -0
- package/dist/esm/worker/messageBus.js +22 -2
- package/dist/types/bip322/index.d.ts +55 -0
- package/dist/types/index.d.ts +3 -2
- package/dist/types/intent/index.d.ts +13 -0
- package/dist/types/repositories/indexedDB/db.d.ts +2 -54
- package/dist/types/repositories/realm/contractRepository.d.ts +24 -0
- package/dist/types/repositories/realm/index.d.ts +4 -0
- package/dist/types/repositories/realm/schemas.d.ts +208 -0
- package/dist/types/repositories/realm/types.d.ts +16 -0
- package/dist/types/repositories/realm/walletRepository.d.ts +31 -0
- package/dist/types/repositories/serialization.d.ts +40 -0
- package/dist/types/repositories/sqlite/contractRepository.d.ts +33 -0
- package/dist/types/repositories/sqlite/index.d.ts +3 -0
- package/dist/types/repositories/sqlite/types.d.ts +18 -0
- package/dist/types/repositories/sqlite/walletRepository.d.ts +40 -0
- package/package.json +18 -14
- package/dist/cjs/adapters/expo-db.js +0 -35
- package/dist/esm/adapters/expo-db.js +0 -27
- package/dist/types/adapters/expo-db.d.ts +0 -7
- /package/dist/cjs/{db → repositories/indexedDB}/manager.js +0 -0
- /package/dist/esm/{db → repositories/indexedDB}/manager.js +0 -0
- /package/dist/types/{db → repositories/indexedDB}/manager.d.ts +0 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RealmContractRepository = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Realm-based implementation of ContractRepository.
|
|
6
|
+
*
|
|
7
|
+
* Consumers must open Realm with the schemas from `./schemas.ts` and pass
|
|
8
|
+
* the instance to the constructor.
|
|
9
|
+
*
|
|
10
|
+
* Realm handles schema creation on open, so `ensureInit()` is a no-op.
|
|
11
|
+
* The consumer owns the Realm lifecycle — `[Symbol.asyncDispose]` is a no-op.
|
|
12
|
+
*/
|
|
13
|
+
class RealmContractRepository {
|
|
14
|
+
constructor(realm) {
|
|
15
|
+
this.realm = realm;
|
|
16
|
+
this.version = 1;
|
|
17
|
+
}
|
|
18
|
+
// ── Lifecycle ──────────────────────────────────────────────────────
|
|
19
|
+
async ensureInit() {
|
|
20
|
+
// Realm handles schema on open — nothing to initialise.
|
|
21
|
+
}
|
|
22
|
+
async [Symbol.asyncDispose]() {
|
|
23
|
+
// no-op — consumer owns the Realm lifecycle
|
|
24
|
+
}
|
|
25
|
+
// ── Clear ──────────────────────────────────────────────────────────
|
|
26
|
+
async clear() {
|
|
27
|
+
await this.ensureInit();
|
|
28
|
+
this.realm.write(() => {
|
|
29
|
+
this.realm.delete(this.realm.objects("ArkContract"));
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
// ── Contract management ────────────────────────────────────────────
|
|
33
|
+
async getContracts(filter) {
|
|
34
|
+
await this.ensureInit();
|
|
35
|
+
let results = this.realm.objects("ArkContract");
|
|
36
|
+
if (filter) {
|
|
37
|
+
const filterParts = [];
|
|
38
|
+
const filterArgs = [];
|
|
39
|
+
let argIndex = 0;
|
|
40
|
+
argIndex = this.addFilterCondition(filterParts, filterArgs, "script", filter.script, argIndex);
|
|
41
|
+
argIndex = this.addFilterCondition(filterParts, filterArgs, "state", filter.state, argIndex);
|
|
42
|
+
argIndex = this.addFilterCondition(filterParts, filterArgs, "type", filter.type, argIndex);
|
|
43
|
+
if (filterParts.length > 0) {
|
|
44
|
+
const query = filterParts.join(" AND ");
|
|
45
|
+
results = results.filtered(query, ...filterArgs);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return [...results].map(contractObjectToDomain);
|
|
49
|
+
}
|
|
50
|
+
async saveContract(contract) {
|
|
51
|
+
await this.ensureInit();
|
|
52
|
+
this.realm.write(() => {
|
|
53
|
+
this.realm.create("ArkContract", {
|
|
54
|
+
script: contract.script,
|
|
55
|
+
address: contract.address,
|
|
56
|
+
type: contract.type,
|
|
57
|
+
state: contract.state,
|
|
58
|
+
paramsJson: JSON.stringify(contract.params),
|
|
59
|
+
createdAt: contract.createdAt,
|
|
60
|
+
expiresAt: contract.expiresAt ?? null,
|
|
61
|
+
label: contract.label ?? null,
|
|
62
|
+
metadataJson: contract.metadata
|
|
63
|
+
? JSON.stringify(contract.metadata)
|
|
64
|
+
: null,
|
|
65
|
+
}, "modified");
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
async deleteContract(script) {
|
|
69
|
+
await this.ensureInit();
|
|
70
|
+
this.realm.write(() => {
|
|
71
|
+
const toDelete = this.realm
|
|
72
|
+
.objects("ArkContract")
|
|
73
|
+
.filtered("script == $0", script);
|
|
74
|
+
this.realm.delete(toDelete);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
// ── Helpers ─────────────────────────────────────────────────────────
|
|
78
|
+
addFilterCondition(parts, args, column, value, argIndex) {
|
|
79
|
+
if (value === undefined)
|
|
80
|
+
return argIndex;
|
|
81
|
+
if (Array.isArray(value)) {
|
|
82
|
+
if (value.length === 0)
|
|
83
|
+
return argIndex;
|
|
84
|
+
const conditions = value.map((_, i) => {
|
|
85
|
+
return `${column} == $${argIndex + i}`;
|
|
86
|
+
});
|
|
87
|
+
parts.push(`(${conditions.join(" OR ")})`);
|
|
88
|
+
args.push(...value);
|
|
89
|
+
return argIndex + value.length;
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
parts.push(`${column} == $${argIndex}`);
|
|
93
|
+
args.push(value);
|
|
94
|
+
return argIndex + 1;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
exports.RealmContractRepository = RealmContractRepository;
|
|
99
|
+
// ── Realm object → Domain converter ──────────────────────────────────────
|
|
100
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
101
|
+
function contractObjectToDomain(obj) {
|
|
102
|
+
const contract = {
|
|
103
|
+
script: obj.script,
|
|
104
|
+
address: obj.address,
|
|
105
|
+
type: obj.type,
|
|
106
|
+
state: obj.state,
|
|
107
|
+
params: JSON.parse(obj.paramsJson),
|
|
108
|
+
createdAt: obj.createdAt,
|
|
109
|
+
};
|
|
110
|
+
if (obj.expiresAt !== null && obj.expiresAt !== undefined) {
|
|
111
|
+
contract.expiresAt = obj.expiresAt;
|
|
112
|
+
}
|
|
113
|
+
if (obj.label !== null && obj.label !== undefined) {
|
|
114
|
+
contract.label = obj.label;
|
|
115
|
+
}
|
|
116
|
+
if (obj.metadataJson !== null && obj.metadataJson !== undefined) {
|
|
117
|
+
contract.metadata = JSON.parse(obj.metadataJson);
|
|
118
|
+
}
|
|
119
|
+
return contract;
|
|
120
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ArkRealmSchemas = exports.RealmContractRepository = exports.RealmWalletRepository = void 0;
|
|
4
|
+
var walletRepository_1 = require("./walletRepository");
|
|
5
|
+
Object.defineProperty(exports, "RealmWalletRepository", { enumerable: true, get: function () { return walletRepository_1.RealmWalletRepository; } });
|
|
6
|
+
var contractRepository_1 = require("./contractRepository");
|
|
7
|
+
Object.defineProperty(exports, "RealmContractRepository", { enumerable: true, get: function () { return contractRepository_1.RealmContractRepository; } });
|
|
8
|
+
var schemas_1 = require("./schemas");
|
|
9
|
+
Object.defineProperty(exports, "ArkRealmSchemas", { enumerable: true, get: function () { return schemas_1.ArkRealmSchemas; } });
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Realm object schemas for the Ark wallet.
|
|
4
|
+
*
|
|
5
|
+
* All schema names are prefixed with "Ark" to avoid collisions with
|
|
6
|
+
* other Realm schemas in the consuming application.
|
|
7
|
+
*
|
|
8
|
+
* Since `realm` is a peer dependency (not installed in this package),
|
|
9
|
+
* schemas are defined as plain JS objects conforming to Realm's
|
|
10
|
+
* ObjectSchema shape.
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.ArkRealmSchemas = exports.ArkContractSchema = exports.ArkWalletStateSchema = exports.ArkTransactionSchema = exports.ArkUtxoSchema = exports.ArkVtxoSchema = void 0;
|
|
14
|
+
exports.ArkVtxoSchema = {
|
|
15
|
+
name: "ArkVtxo",
|
|
16
|
+
primaryKey: "pk",
|
|
17
|
+
properties: {
|
|
18
|
+
pk: "string", // composite: `${txid}:${vout}`
|
|
19
|
+
address: { type: "string", indexed: true },
|
|
20
|
+
txid: "string",
|
|
21
|
+
vout: "int",
|
|
22
|
+
value: "int",
|
|
23
|
+
tapTree: "string", // hex-encoded
|
|
24
|
+
forfeitCb: "string",
|
|
25
|
+
forfeitS: "string",
|
|
26
|
+
intentCb: "string",
|
|
27
|
+
intentS: "string",
|
|
28
|
+
extraWitnessJson: "string?",
|
|
29
|
+
statusJson: "string",
|
|
30
|
+
virtualStatusJson: "string",
|
|
31
|
+
spentBy: "string?",
|
|
32
|
+
settledBy: "string?",
|
|
33
|
+
arkTxId: "string?",
|
|
34
|
+
createdAt: "string", // ISO 8601
|
|
35
|
+
isUnrolled: "bool",
|
|
36
|
+
isSpent: "bool?",
|
|
37
|
+
assetsJson: "string?",
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
exports.ArkUtxoSchema = {
|
|
41
|
+
name: "ArkUtxo",
|
|
42
|
+
primaryKey: "pk",
|
|
43
|
+
properties: {
|
|
44
|
+
pk: "string", // composite: `${txid}:${vout}`
|
|
45
|
+
address: { type: "string", indexed: true },
|
|
46
|
+
txid: "string",
|
|
47
|
+
vout: "int",
|
|
48
|
+
value: "int",
|
|
49
|
+
tapTree: "string", // hex-encoded
|
|
50
|
+
forfeitCb: "string",
|
|
51
|
+
forfeitS: "string",
|
|
52
|
+
intentCb: "string",
|
|
53
|
+
intentS: "string",
|
|
54
|
+
extraWitnessJson: "string?",
|
|
55
|
+
statusJson: "string",
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
exports.ArkTransactionSchema = {
|
|
59
|
+
name: "ArkTransaction",
|
|
60
|
+
primaryKey: "pk",
|
|
61
|
+
properties: {
|
|
62
|
+
pk: "string", // composite: `${address}:${boardingTxid}:${commitmentTxid}:${arkTxid}`
|
|
63
|
+
address: { type: "string", indexed: true },
|
|
64
|
+
boardingTxid: "string",
|
|
65
|
+
commitmentTxid: "string",
|
|
66
|
+
arkTxid: "string",
|
|
67
|
+
type: "string",
|
|
68
|
+
amount: "int",
|
|
69
|
+
settled: "bool",
|
|
70
|
+
createdAt: "int",
|
|
71
|
+
assetsJson: "string?",
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
exports.ArkWalletStateSchema = {
|
|
75
|
+
name: "ArkWalletState",
|
|
76
|
+
primaryKey: "key",
|
|
77
|
+
properties: {
|
|
78
|
+
key: "string",
|
|
79
|
+
lastSyncTime: "int?",
|
|
80
|
+
settingsJson: "string?",
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
exports.ArkContractSchema = {
|
|
84
|
+
name: "ArkContract",
|
|
85
|
+
primaryKey: "script",
|
|
86
|
+
properties: {
|
|
87
|
+
script: "string",
|
|
88
|
+
address: "string",
|
|
89
|
+
type: { type: "string", indexed: true },
|
|
90
|
+
state: { type: "string", indexed: true },
|
|
91
|
+
paramsJson: "string",
|
|
92
|
+
createdAt: "int",
|
|
93
|
+
expiresAt: "int?",
|
|
94
|
+
label: "string?",
|
|
95
|
+
metadataJson: "string?",
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* All Realm schemas needed by the Ark wallet repositories.
|
|
100
|
+
* Pass this array to your Realm configuration's `schema` property.
|
|
101
|
+
*/
|
|
102
|
+
exports.ArkRealmSchemas = [
|
|
103
|
+
exports.ArkVtxoSchema,
|
|
104
|
+
exports.ArkUtxoSchema,
|
|
105
|
+
exports.ArkTransactionSchema,
|
|
106
|
+
exports.ArkWalletStateSchema,
|
|
107
|
+
exports.ArkContractSchema,
|
|
108
|
+
];
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Minimal interface for the subset of the Realm API used by the
|
|
4
|
+
* Ark repositories. Consumers pass their real Realm instance and
|
|
5
|
+
* the compiler validates it satisfies this shape.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RealmWalletRepository = void 0;
|
|
4
|
+
const serialization_1 = require("../serialization");
|
|
5
|
+
/**
|
|
6
|
+
* Realm-based implementation of WalletRepository.
|
|
7
|
+
*
|
|
8
|
+
* Consumers must open Realm with the schemas from `./schemas.ts` and pass
|
|
9
|
+
* the instance to the constructor.
|
|
10
|
+
*
|
|
11
|
+
* Realm handles schema creation on open, so `ensureInit()` is a no-op.
|
|
12
|
+
* The consumer owns the Realm lifecycle — `[Symbol.asyncDispose]` is a no-op.
|
|
13
|
+
*/
|
|
14
|
+
class RealmWalletRepository {
|
|
15
|
+
constructor(realm) {
|
|
16
|
+
this.realm = realm;
|
|
17
|
+
this.version = 1;
|
|
18
|
+
}
|
|
19
|
+
// ── Lifecycle ──────────────────────────────────────────────────────
|
|
20
|
+
async ensureInit() {
|
|
21
|
+
// Realm handles schema on open — nothing to initialise.
|
|
22
|
+
}
|
|
23
|
+
async [Symbol.asyncDispose]() {
|
|
24
|
+
// no-op — consumer owns the Realm lifecycle
|
|
25
|
+
}
|
|
26
|
+
// ── Clear ──────────────────────────────────────────────────────────
|
|
27
|
+
async clear() {
|
|
28
|
+
await this.ensureInit();
|
|
29
|
+
this.realm.write(() => {
|
|
30
|
+
this.realm.delete(this.realm.objects("ArkVtxo"));
|
|
31
|
+
this.realm.delete(this.realm.objects("ArkUtxo"));
|
|
32
|
+
this.realm.delete(this.realm.objects("ArkTransaction"));
|
|
33
|
+
this.realm.delete(this.realm.objects("ArkWalletState"));
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
// ── VTXO management ────────────────────────────────────────────────
|
|
37
|
+
async getVtxos(address) {
|
|
38
|
+
await this.ensureInit();
|
|
39
|
+
const results = this.realm
|
|
40
|
+
.objects("ArkVtxo")
|
|
41
|
+
.filtered("address == $0", address);
|
|
42
|
+
return [...results].map(vtxoObjectToDomain);
|
|
43
|
+
}
|
|
44
|
+
async saveVtxos(address, vtxos) {
|
|
45
|
+
await this.ensureInit();
|
|
46
|
+
this.realm.write(() => {
|
|
47
|
+
for (const vtxo of vtxos) {
|
|
48
|
+
const s = (0, serialization_1.serializeVtxo)(vtxo);
|
|
49
|
+
this.realm.create("ArkVtxo", {
|
|
50
|
+
pk: `${s.txid}:${s.vout}`,
|
|
51
|
+
address,
|
|
52
|
+
txid: s.txid,
|
|
53
|
+
vout: s.vout,
|
|
54
|
+
value: s.value,
|
|
55
|
+
tapTree: s.tapTree,
|
|
56
|
+
forfeitCb: s.forfeitTapLeafScript.cb,
|
|
57
|
+
forfeitS: s.forfeitTapLeafScript.s,
|
|
58
|
+
intentCb: s.intentTapLeafScript.cb,
|
|
59
|
+
intentS: s.intentTapLeafScript.s,
|
|
60
|
+
statusJson: JSON.stringify(s.status),
|
|
61
|
+
virtualStatusJson: JSON.stringify(s.virtualStatus),
|
|
62
|
+
createdAt: typeof s.createdAt === "string"
|
|
63
|
+
? s.createdAt
|
|
64
|
+
: s.createdAt instanceof Date
|
|
65
|
+
? s.createdAt.toISOString()
|
|
66
|
+
: new Date(s.createdAt).toISOString(),
|
|
67
|
+
isUnrolled: s.isUnrolled ?? false,
|
|
68
|
+
isSpent: s.isSpent === undefined ? null : s.isSpent,
|
|
69
|
+
spentBy: s.spentBy ?? null,
|
|
70
|
+
settledBy: s.settledBy ?? null,
|
|
71
|
+
arkTxId: s.arkTxId ?? null,
|
|
72
|
+
extraWitnessJson: s.extraWitness
|
|
73
|
+
? JSON.stringify(s.extraWitness)
|
|
74
|
+
: null,
|
|
75
|
+
assetsJson: s.assets ? JSON.stringify(s.assets) : null,
|
|
76
|
+
}, "modified");
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
async deleteVtxos(address) {
|
|
81
|
+
await this.ensureInit();
|
|
82
|
+
this.realm.write(() => {
|
|
83
|
+
const toDelete = this.realm
|
|
84
|
+
.objects("ArkVtxo")
|
|
85
|
+
.filtered("address == $0", address);
|
|
86
|
+
this.realm.delete(toDelete);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
// ── UTXO management ────────────────────────────────────────────────
|
|
90
|
+
async getUtxos(address) {
|
|
91
|
+
await this.ensureInit();
|
|
92
|
+
const results = this.realm
|
|
93
|
+
.objects("ArkUtxo")
|
|
94
|
+
.filtered("address == $0", address);
|
|
95
|
+
return [...results].map(utxoObjectToDomain);
|
|
96
|
+
}
|
|
97
|
+
async saveUtxos(address, utxos) {
|
|
98
|
+
await this.ensureInit();
|
|
99
|
+
this.realm.write(() => {
|
|
100
|
+
for (const utxo of utxos) {
|
|
101
|
+
const s = (0, serialization_1.serializeUtxo)(utxo);
|
|
102
|
+
this.realm.create("ArkUtxo", {
|
|
103
|
+
pk: `${s.txid}:${s.vout}`,
|
|
104
|
+
address,
|
|
105
|
+
txid: s.txid,
|
|
106
|
+
vout: s.vout,
|
|
107
|
+
value: s.value,
|
|
108
|
+
tapTree: s.tapTree,
|
|
109
|
+
forfeitCb: s.forfeitTapLeafScript.cb,
|
|
110
|
+
forfeitS: s.forfeitTapLeafScript.s,
|
|
111
|
+
intentCb: s.intentTapLeafScript.cb,
|
|
112
|
+
intentS: s.intentTapLeafScript.s,
|
|
113
|
+
statusJson: JSON.stringify(s.status),
|
|
114
|
+
extraWitnessJson: s.extraWitness
|
|
115
|
+
? JSON.stringify(s.extraWitness)
|
|
116
|
+
: null,
|
|
117
|
+
}, "modified");
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
async deleteUtxos(address) {
|
|
122
|
+
await this.ensureInit();
|
|
123
|
+
this.realm.write(() => {
|
|
124
|
+
const toDelete = this.realm
|
|
125
|
+
.objects("ArkUtxo")
|
|
126
|
+
.filtered("address == $0", address);
|
|
127
|
+
this.realm.delete(toDelete);
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
// ── Transaction history ────────────────────────────────────────────
|
|
131
|
+
async getTransactionHistory(address) {
|
|
132
|
+
await this.ensureInit();
|
|
133
|
+
const results = this.realm
|
|
134
|
+
.objects("ArkTransaction")
|
|
135
|
+
.filtered("address == $0", address);
|
|
136
|
+
const txs = [...results].map(txObjectToDomain);
|
|
137
|
+
txs.sort((a, b) => a.createdAt - b.createdAt);
|
|
138
|
+
return txs;
|
|
139
|
+
}
|
|
140
|
+
async saveTransactions(address, txs) {
|
|
141
|
+
await this.ensureInit();
|
|
142
|
+
this.realm.write(() => {
|
|
143
|
+
for (const tx of txs) {
|
|
144
|
+
this.realm.create("ArkTransaction", {
|
|
145
|
+
pk: `${address}:${tx.key.boardingTxid}:${tx.key.commitmentTxid}:${tx.key.arkTxid}`,
|
|
146
|
+
address,
|
|
147
|
+
boardingTxid: tx.key.boardingTxid,
|
|
148
|
+
commitmentTxid: tx.key.commitmentTxid,
|
|
149
|
+
arkTxid: tx.key.arkTxid,
|
|
150
|
+
type: tx.type,
|
|
151
|
+
amount: tx.amount,
|
|
152
|
+
settled: tx.settled,
|
|
153
|
+
createdAt: tx.createdAt,
|
|
154
|
+
assetsJson: tx.assets
|
|
155
|
+
? JSON.stringify(tx.assets)
|
|
156
|
+
: null,
|
|
157
|
+
}, "modified");
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
async deleteTransactions(address) {
|
|
162
|
+
await this.ensureInit();
|
|
163
|
+
this.realm.write(() => {
|
|
164
|
+
const toDelete = this.realm
|
|
165
|
+
.objects("ArkTransaction")
|
|
166
|
+
.filtered("address == $0", address);
|
|
167
|
+
this.realm.delete(toDelete);
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
// ── Wallet state ───────────────────────────────────────────────────
|
|
171
|
+
async getWalletState() {
|
|
172
|
+
await this.ensureInit();
|
|
173
|
+
const results = this.realm
|
|
174
|
+
.objects("ArkWalletState")
|
|
175
|
+
.filtered("key == $0", "state");
|
|
176
|
+
const items = [...results];
|
|
177
|
+
if (items.length === 0)
|
|
178
|
+
return null;
|
|
179
|
+
const obj = items[0];
|
|
180
|
+
const state = {};
|
|
181
|
+
if (obj.lastSyncTime !== null && obj.lastSyncTime !== undefined) {
|
|
182
|
+
state.lastSyncTime = obj.lastSyncTime;
|
|
183
|
+
}
|
|
184
|
+
if (obj.settingsJson) {
|
|
185
|
+
state.settings = JSON.parse(obj.settingsJson);
|
|
186
|
+
}
|
|
187
|
+
return state;
|
|
188
|
+
}
|
|
189
|
+
async saveWalletState(state) {
|
|
190
|
+
await this.ensureInit();
|
|
191
|
+
this.realm.write(() => {
|
|
192
|
+
this.realm.create("ArkWalletState", {
|
|
193
|
+
key: "state",
|
|
194
|
+
lastSyncTime: state.lastSyncTime ?? null,
|
|
195
|
+
settingsJson: state.settings
|
|
196
|
+
? JSON.stringify(state.settings)
|
|
197
|
+
: null,
|
|
198
|
+
}, "modified");
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
exports.RealmWalletRepository = RealmWalletRepository;
|
|
203
|
+
// ── Realm object → Domain converters ─────────────────────────────────────
|
|
204
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
205
|
+
function vtxoObjectToDomain(obj) {
|
|
206
|
+
const serialized = {
|
|
207
|
+
txid: obj.txid,
|
|
208
|
+
vout: obj.vout,
|
|
209
|
+
value: obj.value,
|
|
210
|
+
tapTree: obj.tapTree,
|
|
211
|
+
forfeitTapLeafScript: {
|
|
212
|
+
cb: obj.forfeitCb,
|
|
213
|
+
s: obj.forfeitS,
|
|
214
|
+
},
|
|
215
|
+
intentTapLeafScript: {
|
|
216
|
+
cb: obj.intentCb,
|
|
217
|
+
s: obj.intentS,
|
|
218
|
+
},
|
|
219
|
+
status: JSON.parse(obj.statusJson),
|
|
220
|
+
virtualStatus: JSON.parse(obj.virtualStatusJson),
|
|
221
|
+
createdAt: new Date(obj.createdAt),
|
|
222
|
+
isUnrolled: obj.isUnrolled,
|
|
223
|
+
isSpent: obj.isSpent === null ? undefined : obj.isSpent,
|
|
224
|
+
spentBy: obj.spentBy ?? undefined,
|
|
225
|
+
settledBy: obj.settledBy ?? undefined,
|
|
226
|
+
arkTxId: obj.arkTxId ?? undefined,
|
|
227
|
+
extraWitness: obj.extraWitnessJson
|
|
228
|
+
? JSON.parse(obj.extraWitnessJson)
|
|
229
|
+
: undefined,
|
|
230
|
+
assets: obj.assetsJson ? JSON.parse(obj.assetsJson) : undefined,
|
|
231
|
+
};
|
|
232
|
+
return (0, serialization_1.deserializeVtxo)(serialized);
|
|
233
|
+
}
|
|
234
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
235
|
+
function utxoObjectToDomain(obj) {
|
|
236
|
+
const serialized = {
|
|
237
|
+
txid: obj.txid,
|
|
238
|
+
vout: obj.vout,
|
|
239
|
+
value: obj.value,
|
|
240
|
+
tapTree: obj.tapTree,
|
|
241
|
+
forfeitTapLeafScript: {
|
|
242
|
+
cb: obj.forfeitCb,
|
|
243
|
+
s: obj.forfeitS,
|
|
244
|
+
},
|
|
245
|
+
intentTapLeafScript: {
|
|
246
|
+
cb: obj.intentCb,
|
|
247
|
+
s: obj.intentS,
|
|
248
|
+
},
|
|
249
|
+
status: JSON.parse(obj.statusJson),
|
|
250
|
+
extraWitness: obj.extraWitnessJson
|
|
251
|
+
? JSON.parse(obj.extraWitnessJson)
|
|
252
|
+
: undefined,
|
|
253
|
+
};
|
|
254
|
+
return (0, serialization_1.deserializeUtxo)(serialized);
|
|
255
|
+
}
|
|
256
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
257
|
+
function txObjectToDomain(obj) {
|
|
258
|
+
const tx = {
|
|
259
|
+
key: {
|
|
260
|
+
boardingTxid: obj.boardingTxid,
|
|
261
|
+
commitmentTxid: obj.commitmentTxid,
|
|
262
|
+
arkTxid: obj.arkTxid,
|
|
263
|
+
},
|
|
264
|
+
type: obj.type,
|
|
265
|
+
amount: obj.amount,
|
|
266
|
+
settled: obj.settled,
|
|
267
|
+
createdAt: obj.createdAt,
|
|
268
|
+
};
|
|
269
|
+
if (obj.assetsJson) {
|
|
270
|
+
tx.assets = JSON.parse(obj.assetsJson);
|
|
271
|
+
}
|
|
272
|
+
return tx;
|
|
273
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.deserializeUtxo = exports.deserializeVtxo = exports.deserializeTapLeaf = exports.serializeUtxo = exports.serializeVtxo = exports.serializeTapLeaf = void 0;
|
|
4
|
+
const base_1 = require("@scure/base");
|
|
5
|
+
const btc_signer_1 = require("@scure/btc-signer");
|
|
6
|
+
const serializeTapLeaf = ([cb, s,]) => ({
|
|
7
|
+
cb: base_1.hex.encode(btc_signer_1.TaprootControlBlock.encode(cb)),
|
|
8
|
+
s: base_1.hex.encode(s),
|
|
9
|
+
});
|
|
10
|
+
exports.serializeTapLeaf = serializeTapLeaf;
|
|
11
|
+
const serializeVtxo = (v) => ({
|
|
12
|
+
...v,
|
|
13
|
+
tapTree: base_1.hex.encode(v.tapTree),
|
|
14
|
+
forfeitTapLeafScript: (0, exports.serializeTapLeaf)(v.forfeitTapLeafScript),
|
|
15
|
+
intentTapLeafScript: (0, exports.serializeTapLeaf)(v.intentTapLeafScript),
|
|
16
|
+
extraWitness: v.extraWitness?.map(base_1.hex.encode),
|
|
17
|
+
});
|
|
18
|
+
exports.serializeVtxo = serializeVtxo;
|
|
19
|
+
const serializeUtxo = (u) => ({
|
|
20
|
+
...u,
|
|
21
|
+
tapTree: base_1.hex.encode(u.tapTree),
|
|
22
|
+
forfeitTapLeafScript: (0, exports.serializeTapLeaf)(u.forfeitTapLeafScript),
|
|
23
|
+
intentTapLeafScript: (0, exports.serializeTapLeaf)(u.intentTapLeafScript),
|
|
24
|
+
extraWitness: u.extraWitness?.map(base_1.hex.encode),
|
|
25
|
+
});
|
|
26
|
+
exports.serializeUtxo = serializeUtxo;
|
|
27
|
+
const deserializeTapLeaf = (t) => {
|
|
28
|
+
const cb = btc_signer_1.TaprootControlBlock.decode(base_1.hex.decode(t.cb));
|
|
29
|
+
const s = base_1.hex.decode(t.s);
|
|
30
|
+
return [cb, s];
|
|
31
|
+
};
|
|
32
|
+
exports.deserializeTapLeaf = deserializeTapLeaf;
|
|
33
|
+
const deserializeVtxo = (o) => ({
|
|
34
|
+
...o,
|
|
35
|
+
createdAt: new Date(o.createdAt),
|
|
36
|
+
tapTree: base_1.hex.decode(o.tapTree),
|
|
37
|
+
forfeitTapLeafScript: (0, exports.deserializeTapLeaf)(o.forfeitTapLeafScript),
|
|
38
|
+
intentTapLeafScript: (0, exports.deserializeTapLeaf)(o.intentTapLeafScript),
|
|
39
|
+
extraWitness: o.extraWitness?.map(base_1.hex.decode),
|
|
40
|
+
});
|
|
41
|
+
exports.deserializeVtxo = deserializeVtxo;
|
|
42
|
+
const deserializeUtxo = (o) => ({
|
|
43
|
+
...o,
|
|
44
|
+
tapTree: base_1.hex.decode(o.tapTree),
|
|
45
|
+
forfeitTapLeafScript: (0, exports.deserializeTapLeaf)(o.forfeitTapLeafScript),
|
|
46
|
+
intentTapLeafScript: (0, exports.deserializeTapLeaf)(o.intentTapLeafScript),
|
|
47
|
+
extraWitness: o.extraWitness?.map(base_1.hex.decode),
|
|
48
|
+
});
|
|
49
|
+
exports.deserializeUtxo = deserializeUtxo;
|