@arkade-os/sdk 0.3.12 → 0.4.0-next.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/README.md +483 -54
- package/dist/cjs/adapters/expo-db.js +35 -0
- package/dist/cjs/asset/assetGroup.js +141 -0
- package/dist/cjs/asset/assetId.js +88 -0
- package/dist/cjs/asset/assetInput.js +204 -0
- package/dist/cjs/asset/assetOutput.js +159 -0
- package/dist/cjs/asset/assetRef.js +82 -0
- package/dist/cjs/asset/index.js +24 -0
- package/dist/cjs/asset/metadata.js +172 -0
- package/dist/cjs/asset/packet.js +164 -0
- package/dist/cjs/asset/types.js +25 -0
- package/dist/cjs/asset/utils.js +105 -0
- package/dist/cjs/contracts/arkcontract.js +148 -0
- package/dist/cjs/contracts/contractManager.js +436 -0
- package/dist/cjs/contracts/contractWatcher.js +567 -0
- package/dist/cjs/contracts/handlers/default.js +85 -0
- package/dist/cjs/contracts/handlers/delegate.js +89 -0
- package/dist/cjs/contracts/handlers/helpers.js +105 -0
- package/dist/cjs/contracts/handlers/index.js +19 -0
- package/dist/cjs/contracts/handlers/registry.js +89 -0
- package/dist/cjs/contracts/handlers/vhtlc.js +193 -0
- package/dist/cjs/contracts/index.js +41 -0
- package/dist/cjs/contracts/types.js +2 -0
- package/dist/cjs/db/manager.js +97 -0
- package/dist/cjs/forfeit.js +12 -8
- package/dist/cjs/identity/index.js +1 -0
- package/dist/cjs/identity/seedIdentity.js +255 -0
- package/dist/cjs/index.js +70 -14
- package/dist/cjs/intent/index.js +28 -2
- package/dist/cjs/providers/ark.js +7 -0
- package/dist/cjs/providers/delegator.js +66 -0
- package/dist/cjs/providers/expoIndexer.js +5 -0
- package/dist/cjs/providers/indexer.js +68 -1
- package/dist/cjs/providers/onchain.js +2 -2
- package/dist/cjs/providers/utils.js +1 -0
- package/dist/cjs/repositories/contractRepository.js +0 -103
- package/dist/cjs/repositories/inMemory/contractRepository.js +55 -0
- package/dist/cjs/repositories/inMemory/walletRepository.js +80 -0
- package/dist/cjs/repositories/index.js +16 -0
- package/dist/cjs/repositories/indexedDB/contractRepository.js +187 -0
- package/dist/cjs/repositories/indexedDB/db.js +57 -0
- package/dist/cjs/repositories/indexedDB/schema.js +159 -0
- package/dist/cjs/repositories/indexedDB/walletRepository.js +338 -0
- package/dist/cjs/repositories/indexedDB/websqlAdapter.js +144 -0
- package/dist/cjs/repositories/migrations/contractRepositoryImpl.js +127 -0
- package/dist/cjs/repositories/migrations/fromStorageAdapter.js +66 -0
- package/dist/cjs/repositories/migrations/walletRepositoryImpl.js +180 -0
- package/dist/cjs/repositories/walletRepository.js +0 -169
- package/dist/cjs/script/base.js +54 -0
- package/dist/cjs/script/delegate.js +49 -0
- package/dist/cjs/storage/asyncStorage.js +4 -1
- package/dist/cjs/storage/fileSystem.js +3 -0
- package/dist/cjs/storage/inMemory.js +3 -0
- package/dist/cjs/storage/indexedDB.js +5 -1
- package/dist/cjs/storage/localStorage.js +3 -0
- package/dist/cjs/utils/arkTransaction.js +16 -0
- package/dist/cjs/utils/transactionHistory.js +50 -0
- package/dist/cjs/utils/txSizeEstimator.js +39 -14
- package/dist/cjs/wallet/asset-manager.js +338 -0
- package/dist/cjs/wallet/asset.js +117 -0
- package/dist/cjs/wallet/batch.js +1 -1
- package/dist/cjs/wallet/delegator.js +235 -0
- package/dist/cjs/wallet/expo/background.js +133 -0
- package/dist/cjs/wallet/expo/index.js +9 -0
- package/dist/cjs/wallet/expo/wallet.js +231 -0
- package/dist/cjs/wallet/onchain.js +57 -12
- package/dist/cjs/wallet/serviceWorker/wallet-message-handler.js +568 -0
- package/dist/cjs/wallet/serviceWorker/wallet.js +383 -102
- package/dist/cjs/wallet/unroll.js +7 -2
- package/dist/cjs/wallet/utils.js +60 -0
- package/dist/cjs/wallet/validation.js +151 -0
- package/dist/cjs/wallet/vtxo-manager.js +1 -1
- package/dist/cjs/wallet/wallet.js +702 -260
- package/dist/cjs/worker/browser/service-worker-manager.js +82 -0
- package/dist/cjs/{wallet/serviceWorker → worker/browser}/utils.js +2 -1
- package/dist/cjs/worker/expo/asyncStorageTaskQueue.js +78 -0
- package/dist/cjs/worker/expo/index.js +12 -0
- package/dist/cjs/worker/expo/processors/contractPollProcessor.js +61 -0
- package/dist/cjs/worker/expo/processors/index.js +6 -0
- package/dist/cjs/worker/expo/taskQueue.js +41 -0
- package/dist/cjs/worker/expo/taskRunner.js +57 -0
- package/dist/cjs/worker/messageBus.js +252 -0
- package/dist/esm/adapters/expo-db.js +27 -0
- package/dist/esm/asset/assetGroup.js +137 -0
- package/dist/esm/asset/assetId.js +84 -0
- package/dist/esm/asset/assetInput.js +199 -0
- package/dist/esm/asset/assetOutput.js +154 -0
- package/dist/esm/asset/assetRef.js +78 -0
- package/dist/esm/asset/index.js +8 -0
- package/dist/esm/asset/metadata.js +167 -0
- package/dist/esm/asset/packet.js +159 -0
- package/dist/esm/asset/types.js +22 -0
- package/dist/esm/asset/utils.js +99 -0
- package/dist/esm/contracts/arkcontract.js +141 -0
- package/dist/esm/contracts/contractManager.js +432 -0
- package/dist/esm/contracts/contractWatcher.js +563 -0
- package/dist/esm/contracts/handlers/default.js +82 -0
- package/dist/esm/contracts/handlers/delegate.js +86 -0
- package/dist/esm/contracts/handlers/helpers.js +66 -0
- package/dist/esm/contracts/handlers/index.js +12 -0
- package/dist/esm/contracts/handlers/registry.js +86 -0
- package/dist/esm/contracts/handlers/vhtlc.js +190 -0
- package/dist/esm/contracts/index.js +13 -0
- package/dist/esm/contracts/types.js +1 -0
- package/dist/esm/db/manager.js +92 -0
- package/dist/esm/forfeit.js +11 -8
- package/dist/esm/identity/index.js +1 -0
- package/dist/esm/identity/seedIdentity.js +249 -0
- package/dist/esm/index.js +25 -15
- package/dist/esm/intent/index.js +28 -2
- package/dist/esm/providers/ark.js +7 -0
- package/dist/esm/providers/delegator.js +62 -0
- package/dist/esm/providers/expoIndexer.js +5 -0
- package/dist/esm/providers/indexer.js +68 -1
- package/dist/esm/providers/onchain.js +2 -2
- package/dist/esm/providers/utils.js +1 -0
- package/dist/esm/repositories/contractRepository.js +1 -101
- package/dist/esm/repositories/inMemory/contractRepository.js +51 -0
- package/dist/esm/repositories/inMemory/walletRepository.js +76 -0
- package/dist/esm/repositories/index.js +8 -0
- package/dist/esm/repositories/indexedDB/contractRepository.js +183 -0
- package/dist/esm/repositories/indexedDB/db.js +42 -0
- package/dist/esm/repositories/indexedDB/schema.js +155 -0
- package/dist/esm/repositories/indexedDB/walletRepository.js +334 -0
- package/dist/esm/repositories/indexedDB/websqlAdapter.js +138 -0
- package/dist/esm/repositories/migrations/contractRepositoryImpl.js +121 -0
- package/dist/esm/repositories/migrations/fromStorageAdapter.js +58 -0
- package/dist/esm/repositories/migrations/walletRepositoryImpl.js +176 -0
- package/dist/esm/repositories/walletRepository.js +1 -167
- package/dist/esm/script/base.js +21 -1
- package/dist/esm/script/delegate.js +46 -0
- package/dist/esm/storage/asyncStorage.js +4 -1
- package/dist/esm/storage/fileSystem.js +3 -0
- package/dist/esm/storage/inMemory.js +3 -0
- package/dist/esm/storage/indexedDB.js +5 -1
- package/dist/esm/storage/localStorage.js +3 -0
- package/dist/esm/utils/arkTransaction.js +15 -0
- package/dist/esm/utils/transactionHistory.js +50 -0
- package/dist/esm/utils/txSizeEstimator.js +39 -14
- package/dist/esm/wallet/asset-manager.js +333 -0
- package/dist/esm/wallet/asset.js +111 -0
- package/dist/esm/wallet/batch.js +1 -1
- package/dist/esm/wallet/delegator.js +231 -0
- package/dist/esm/wallet/expo/background.js +128 -0
- package/dist/esm/wallet/expo/index.js +2 -0
- package/dist/esm/wallet/expo/wallet.js +194 -0
- package/dist/esm/wallet/onchain.js +57 -12
- package/dist/esm/wallet/serviceWorker/wallet-message-handler.js +564 -0
- package/dist/esm/wallet/serviceWorker/wallet.js +382 -101
- package/dist/esm/wallet/unroll.js +7 -2
- package/dist/esm/wallet/utils.js +55 -0
- package/dist/esm/wallet/validation.js +139 -0
- package/dist/esm/wallet/vtxo-manager.js +1 -1
- package/dist/esm/wallet/wallet.js +704 -229
- package/dist/esm/worker/browser/service-worker-manager.js +76 -0
- package/dist/esm/{wallet/serviceWorker → worker/browser}/utils.js +2 -1
- package/dist/esm/worker/expo/asyncStorageTaskQueue.js +74 -0
- package/dist/esm/worker/expo/index.js +4 -0
- package/dist/esm/worker/expo/processors/contractPollProcessor.js +58 -0
- package/dist/esm/worker/expo/processors/index.js +1 -0
- package/dist/esm/worker/expo/taskQueue.js +37 -0
- package/dist/esm/worker/expo/taskRunner.js +54 -0
- package/dist/esm/worker/messageBus.js +248 -0
- package/dist/types/adapters/expo-db.d.ts +7 -0
- package/dist/types/asset/assetGroup.d.ts +28 -0
- package/dist/types/asset/assetId.d.ts +19 -0
- package/dist/types/asset/assetInput.d.ts +46 -0
- package/dist/types/asset/assetOutput.d.ts +39 -0
- package/dist/types/asset/assetRef.d.ts +25 -0
- package/dist/types/asset/index.d.ts +8 -0
- package/dist/types/asset/metadata.d.ts +37 -0
- package/dist/types/asset/packet.d.ts +27 -0
- package/dist/types/asset/types.d.ts +18 -0
- package/dist/types/asset/utils.d.ts +21 -0
- package/dist/types/contracts/arkcontract.d.ts +101 -0
- package/dist/types/contracts/contractManager.d.ts +331 -0
- package/dist/types/contracts/contractWatcher.d.ts +192 -0
- package/dist/types/contracts/handlers/default.d.ts +19 -0
- package/dist/types/contracts/handlers/delegate.d.ts +21 -0
- package/dist/types/contracts/handlers/helpers.d.ts +18 -0
- package/dist/types/contracts/handlers/index.d.ts +7 -0
- package/dist/types/contracts/handlers/registry.d.ts +65 -0
- package/dist/types/contracts/handlers/vhtlc.d.ts +32 -0
- package/dist/types/contracts/index.d.ts +14 -0
- package/dist/types/contracts/types.d.ts +222 -0
- package/dist/types/db/manager.d.ts +22 -0
- package/dist/types/forfeit.d.ts +2 -1
- package/dist/types/identity/index.d.ts +1 -0
- package/dist/types/identity/seedIdentity.d.ts +128 -0
- package/dist/types/index.d.ts +21 -12
- package/dist/types/intent/index.d.ts +2 -1
- package/dist/types/providers/ark.d.ts +11 -2
- package/dist/types/providers/delegator.d.ts +29 -0
- package/dist/types/providers/indexer.d.ts +11 -1
- package/dist/types/repositories/contractRepository.d.ts +30 -19
- package/dist/types/repositories/inMemory/contractRepository.d.ts +17 -0
- package/dist/types/repositories/inMemory/walletRepository.d.ts +26 -0
- package/dist/types/repositories/index.d.ts +7 -0
- package/dist/types/repositories/indexedDB/contractRepository.d.ts +21 -0
- package/dist/types/repositories/indexedDB/db.d.ts +56 -0
- package/dist/types/repositories/indexedDB/schema.d.ts +8 -0
- package/dist/types/repositories/indexedDB/walletRepository.d.ts +25 -0
- package/dist/types/repositories/indexedDB/websqlAdapter.d.ts +49 -0
- package/dist/types/repositories/migrations/contractRepositoryImpl.d.ts +24 -0
- package/dist/types/repositories/migrations/fromStorageAdapter.d.ts +19 -0
- package/dist/types/repositories/migrations/walletRepositoryImpl.d.ts +27 -0
- package/dist/types/repositories/walletRepository.d.ts +13 -24
- package/dist/types/script/base.d.ts +1 -0
- package/dist/types/script/delegate.d.ts +36 -0
- package/dist/types/storage/asyncStorage.d.ts +4 -0
- package/dist/types/storage/fileSystem.d.ts +3 -0
- package/dist/types/storage/inMemory.d.ts +3 -0
- package/dist/types/storage/index.d.ts +3 -0
- package/dist/types/storage/indexedDB.d.ts +3 -0
- package/dist/types/storage/localStorage.d.ts +3 -0
- package/dist/types/utils/arkTransaction.d.ts +6 -0
- package/dist/types/utils/txSizeEstimator.d.ts +12 -2
- package/dist/types/wallet/asset-manager.d.ts +78 -0
- package/dist/types/wallet/asset.d.ts +21 -0
- package/dist/types/wallet/batch.d.ts +1 -1
- package/dist/types/wallet/delegator.d.ts +24 -0
- package/dist/types/wallet/expo/background.d.ts +66 -0
- package/dist/types/wallet/expo/index.d.ts +4 -0
- package/dist/types/wallet/expo/wallet.d.ts +97 -0
- package/dist/types/wallet/index.d.ts +75 -2
- package/dist/types/wallet/onchain.d.ts +22 -1
- package/dist/types/wallet/serviceWorker/wallet-message-handler.d.ts +366 -0
- package/dist/types/wallet/serviceWorker/wallet.d.ts +20 -11
- package/dist/types/wallet/utils.d.ts +13 -1
- package/dist/types/wallet/validation.d.ts +24 -0
- package/dist/types/wallet/wallet.d.ts +111 -17
- package/dist/types/worker/browser/service-worker-manager.d.ts +21 -0
- package/dist/types/{wallet/serviceWorker → worker/browser}/utils.d.ts +2 -1
- package/dist/types/worker/expo/asyncStorageTaskQueue.d.ts +46 -0
- package/dist/types/worker/expo/index.d.ts +7 -0
- package/dist/types/worker/expo/processors/contractPollProcessor.d.ts +14 -0
- package/dist/types/worker/expo/processors/index.d.ts +1 -0
- package/dist/types/worker/expo/taskQueue.d.ts +50 -0
- package/dist/types/worker/expo/taskRunner.d.ts +42 -0
- package/dist/types/worker/messageBus.d.ts +109 -0
- package/package.json +71 -17
- package/dist/cjs/wallet/serviceWorker/request.js +0 -78
- package/dist/cjs/wallet/serviceWorker/response.js +0 -222
- package/dist/cjs/wallet/serviceWorker/worker.js +0 -655
- package/dist/esm/wallet/serviceWorker/request.js +0 -75
- package/dist/esm/wallet/serviceWorker/response.js +0 -219
- package/dist/esm/wallet/serviceWorker/worker.js +0 -651
- package/dist/types/wallet/serviceWorker/request.d.ts +0 -74
- package/dist/types/wallet/serviceWorker/response.d.ts +0 -123
- package/dist/types/wallet/serviceWorker/worker.d.ts +0 -53
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.ExpoWallet = void 0;
|
|
37
|
+
const base_1 = require("@scure/base");
|
|
38
|
+
const wallet_1 = require("../wallet");
|
|
39
|
+
const ark_1 = require("../../providers/ark");
|
|
40
|
+
const taskRunner_1 = require("../../worker/expo/taskRunner");
|
|
41
|
+
const processors_1 = require("../../worker/expo/processors");
|
|
42
|
+
const utils_1 = require("../utils");
|
|
43
|
+
const default_1 = require("../../script/default");
|
|
44
|
+
/**
|
|
45
|
+
* Expo/React Native wallet with built-in background task processing.
|
|
46
|
+
*
|
|
47
|
+
* Wraps a standard {@link Wallet} and adds a lightweight task queue
|
|
48
|
+
* for keeping contract/VTXO state fresh while the app is active and
|
|
49
|
+
* across Expo BackgroundTask wakes.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* import { ExpoWallet } from "@arkade-os/sdk/wallet/expo";
|
|
54
|
+
* import { AsyncStorageTaskQueue } from "@arkade-os/sdk/worker/expo";
|
|
55
|
+
*
|
|
56
|
+
* const wallet = await ExpoWallet.setup({
|
|
57
|
+
* identity: SingleKey.fromHex(privateKey),
|
|
58
|
+
* arkServerUrl,
|
|
59
|
+
* esploraUrl,
|
|
60
|
+
* storage: { walletRepository, contractRepository },
|
|
61
|
+
* background: {
|
|
62
|
+
* taskName: "ark-background-poll",
|
|
63
|
+
* taskQueue: new AsyncStorageTaskQueue(AsyncStorage),
|
|
64
|
+
* foregroundIntervalMs: 20_000,
|
|
65
|
+
* minimumBackgroundInterval: 15,
|
|
66
|
+
* },
|
|
67
|
+
* });
|
|
68
|
+
*
|
|
69
|
+
* const balance = await wallet.getBalance();
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
class ExpoWallet {
|
|
73
|
+
constructor(wallet, taskQueue, processors, deps, taskName, foregroundIntervalMs) {
|
|
74
|
+
this.wallet = wallet;
|
|
75
|
+
this.taskQueue = taskQueue;
|
|
76
|
+
this.processors = processors;
|
|
77
|
+
this.deps = deps;
|
|
78
|
+
this.identity = wallet.identity;
|
|
79
|
+
this.arkProvider = wallet.arkProvider;
|
|
80
|
+
this.indexerProvider = wallet.indexerProvider;
|
|
81
|
+
this.taskName = taskName;
|
|
82
|
+
if (foregroundIntervalMs && foregroundIntervalMs > 0) {
|
|
83
|
+
this.startForegroundPolling(foregroundIntervalMs);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Create an ExpoWallet with background task support.
|
|
88
|
+
*
|
|
89
|
+
* 1. Creates the inner {@link Wallet} via `Wallet.create()`.
|
|
90
|
+
* 2. Wires up processors (defaults to {@link contractPollProcessor}).
|
|
91
|
+
* 3. Persists background config for the background handler (if the queue supports it).
|
|
92
|
+
* 4. Seeds the task queue with a `contract-poll` task.
|
|
93
|
+
* 5. Registers the background task with the OS scheduler (if `minimumBackgroundInterval` is set).
|
|
94
|
+
* 6. Starts foreground polling if `foregroundIntervalMs` is set.
|
|
95
|
+
*/
|
|
96
|
+
static async setup(config) {
|
|
97
|
+
const wallet = await wallet_1.Wallet.create(config);
|
|
98
|
+
const processors = config.background.processors ?? [
|
|
99
|
+
processors_1.contractPollProcessor,
|
|
100
|
+
];
|
|
101
|
+
const deps = {
|
|
102
|
+
walletRepository: wallet.walletRepository,
|
|
103
|
+
contractRepository: wallet.contractRepository,
|
|
104
|
+
indexerProvider: wallet.indexerProvider,
|
|
105
|
+
arkProvider: wallet.arkProvider,
|
|
106
|
+
extendVtxo: (vtxo, contract) => {
|
|
107
|
+
if (contract) {
|
|
108
|
+
return (0, utils_1.extendVtxoFromContract)(vtxo, contract);
|
|
109
|
+
}
|
|
110
|
+
return (0, utils_1.extendVirtualCoin)(wallet, vtxo);
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
const { taskQueue } = config.background;
|
|
114
|
+
// Persist wallet params so the background handler can rehydrate
|
|
115
|
+
// without a network call. Only works with AsyncStorageTaskQueue.
|
|
116
|
+
if ("persistConfig" in taskQueue) {
|
|
117
|
+
const arkServerUrl = config.arkServerUrl ??
|
|
118
|
+
(wallet.arkProvider instanceof ark_1.RestArkProvider
|
|
119
|
+
? wallet.arkProvider.serverUrl
|
|
120
|
+
: undefined);
|
|
121
|
+
if (arkServerUrl) {
|
|
122
|
+
const timelock = wallet.offchainTapscript.options.csvTimelock ??
|
|
123
|
+
default_1.DefaultVtxo.Script.DEFAULT_TIMELOCK;
|
|
124
|
+
const bgConfig = {
|
|
125
|
+
arkServerUrl,
|
|
126
|
+
pubkeyHex: base_1.hex.encode(wallet.offchainTapscript.options.pubKey),
|
|
127
|
+
serverPubKeyHex: base_1.hex.encode(wallet.offchainTapscript.options.serverPubKey),
|
|
128
|
+
exitTimelockValue: timelock.value.toString(),
|
|
129
|
+
exitTimelockType: timelock.type,
|
|
130
|
+
};
|
|
131
|
+
await taskQueue.persistConfig(bgConfig);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
const expoWallet = new ExpoWallet(wallet, taskQueue, processors, deps, config.background.taskName, config.background.foregroundIntervalMs);
|
|
135
|
+
// Seed the queue so the first tick (or background wake) has work to do
|
|
136
|
+
await expoWallet.seedContractPollTask();
|
|
137
|
+
// Activate OS-level background scheduling
|
|
138
|
+
if (config.background.minimumBackgroundInterval) {
|
|
139
|
+
try {
|
|
140
|
+
const { registerExpoBackgroundTask } = await Promise.resolve().then(() => __importStar(require("./background")));
|
|
141
|
+
await registerExpoBackgroundTask(config.background.taskName, {
|
|
142
|
+
minimumInterval: config.background.minimumBackgroundInterval,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
// expo-background-task not installed — foreground-only mode
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return expoWallet;
|
|
150
|
+
}
|
|
151
|
+
// ── Foreground polling ───────────────────────────────────────────
|
|
152
|
+
startForegroundPolling(intervalMs) {
|
|
153
|
+
this.foregroundIntervalId = setInterval(() => {
|
|
154
|
+
this.runForegroundPoll().catch(console.error);
|
|
155
|
+
}, intervalMs);
|
|
156
|
+
}
|
|
157
|
+
async runForegroundPoll() {
|
|
158
|
+
await (0, taskRunner_1.runTasks)(this.taskQueue, this.processors, this.deps);
|
|
159
|
+
// Consume results immediately (no background handoff needed)
|
|
160
|
+
const results = await this.taskQueue.getResults();
|
|
161
|
+
if (results.length > 0) {
|
|
162
|
+
await this.taskQueue.acknowledgeResults(results.map((r) => r.id));
|
|
163
|
+
}
|
|
164
|
+
// Re-seed for the next tick
|
|
165
|
+
await this.seedContractPollTask();
|
|
166
|
+
}
|
|
167
|
+
async seedContractPollTask() {
|
|
168
|
+
const existing = await this.taskQueue.getTasks(processors_1.CONTRACT_POLL_TASK_TYPE);
|
|
169
|
+
if (existing.length > 0)
|
|
170
|
+
return;
|
|
171
|
+
const task = {
|
|
172
|
+
id: (0, utils_1.getRandomId)(),
|
|
173
|
+
type: processors_1.CONTRACT_POLL_TASK_TYPE,
|
|
174
|
+
data: {},
|
|
175
|
+
createdAt: Date.now(),
|
|
176
|
+
};
|
|
177
|
+
await this.taskQueue.addTask(task);
|
|
178
|
+
}
|
|
179
|
+
// ── Lifecycle ────────────────────────────────────────────────────
|
|
180
|
+
/**
|
|
181
|
+
* Stop foreground polling and unregister the background task.
|
|
182
|
+
*/
|
|
183
|
+
async dispose() {
|
|
184
|
+
if (this.foregroundIntervalId) {
|
|
185
|
+
clearInterval(this.foregroundIntervalId);
|
|
186
|
+
this.foregroundIntervalId = undefined;
|
|
187
|
+
}
|
|
188
|
+
try {
|
|
189
|
+
const { unregisterExpoBackgroundTask } = await Promise.resolve().then(() => __importStar(require("./background")));
|
|
190
|
+
await unregisterExpoBackgroundTask(this.taskName);
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
// expo-background-task not installed — nothing to unregister
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
// ── IWallet delegation ───────────────────────────────────────────
|
|
197
|
+
getAddress() {
|
|
198
|
+
return this.wallet.getAddress();
|
|
199
|
+
}
|
|
200
|
+
getBoardingAddress() {
|
|
201
|
+
return this.wallet.getBoardingAddress();
|
|
202
|
+
}
|
|
203
|
+
getBalance() {
|
|
204
|
+
return this.wallet.getBalance();
|
|
205
|
+
}
|
|
206
|
+
getVtxos(filter) {
|
|
207
|
+
return this.wallet.getVtxos(filter);
|
|
208
|
+
}
|
|
209
|
+
getBoardingUtxos() {
|
|
210
|
+
return this.wallet.getBoardingUtxos();
|
|
211
|
+
}
|
|
212
|
+
getTransactionHistory() {
|
|
213
|
+
return this.wallet.getTransactionHistory();
|
|
214
|
+
}
|
|
215
|
+
getContractManager() {
|
|
216
|
+
return this.wallet.getContractManager();
|
|
217
|
+
}
|
|
218
|
+
sendBitcoin(params) {
|
|
219
|
+
return this.wallet.sendBitcoin(params);
|
|
220
|
+
}
|
|
221
|
+
settle(params, eventCallback) {
|
|
222
|
+
return this.wallet.settle(params, eventCallback);
|
|
223
|
+
}
|
|
224
|
+
send(...recipients) {
|
|
225
|
+
return this.wallet.send(...recipients);
|
|
226
|
+
}
|
|
227
|
+
get assetManager() {
|
|
228
|
+
return this.wallet.assetManager;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
exports.ExpoWallet = ExpoWallet;
|
|
@@ -8,6 +8,7 @@ const onchain_1 = require("../providers/onchain");
|
|
|
8
8
|
const anchor_1 = require("../utils/anchor");
|
|
9
9
|
const txSizeEstimator_1 = require("../utils/txSizeEstimator");
|
|
10
10
|
const transaction_1 = require("../utils/transaction");
|
|
11
|
+
const utils_1 = require("./utils");
|
|
11
12
|
/**
|
|
12
13
|
* Onchain Bitcoin wallet implementation for traditional Bitcoin transactions.
|
|
13
14
|
*
|
|
@@ -59,11 +60,58 @@ class OnchainWallet {
|
|
|
59
60
|
const onchainTotal = onchainConfirmed + onchainUnconfirmed;
|
|
60
61
|
return onchainTotal;
|
|
61
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Iteratively selects coins and estimates transaction fees until convergence.
|
|
65
|
+
*
|
|
66
|
+
* This method handles the circular dependency between coin selection and fee
|
|
67
|
+
* estimation: the fee depends on transaction size, which depends on the number
|
|
68
|
+
* of inputs (selected coins) and whether a change output is needed.
|
|
69
|
+
*
|
|
70
|
+
* The algorithm iterates up to 10 times, refining the fee estimate based on
|
|
71
|
+
* the actual transaction structure. It resolves dust oscillation loops that
|
|
72
|
+
* occur when the change amount hovers near the dust threshold—adding/removing
|
|
73
|
+
* the change output causes the fee to fluctuate, preventing convergence.
|
|
74
|
+
* When a lower fee is computed (indicating the change output was dropped),
|
|
75
|
+
* the function accepts this state to guarantee termination.
|
|
76
|
+
*
|
|
77
|
+
* @param coins - Available coins to select from
|
|
78
|
+
* @param amount - Target send amount in satoshis
|
|
79
|
+
* @param feeRate - Fee rate in sat/vbyte
|
|
80
|
+
* @param recipientAddress - Destination address for size estimation
|
|
81
|
+
* @returns Selected inputs, change amount, and calculated fee
|
|
82
|
+
* @throws Error if fee estimation fails to converge within max iterations
|
|
83
|
+
*/
|
|
84
|
+
estimateFeesAndSelectCoins(coins, amount, feeRate, recipientAddress) {
|
|
85
|
+
const MAX_ITERATIONS = 10;
|
|
86
|
+
let fee = 0;
|
|
87
|
+
for (let i = 0; i < MAX_ITERATIONS; i++) {
|
|
88
|
+
const totalNeeded = amount + fee;
|
|
89
|
+
const selected = selectCoins(coins, totalNeeded);
|
|
90
|
+
const estimator = txSizeEstimator_1.TxWeightEstimator.create();
|
|
91
|
+
for (const _ of selected.inputs) {
|
|
92
|
+
estimator.addKeySpendInput();
|
|
93
|
+
}
|
|
94
|
+
estimator.addOutputAddress(recipientAddress, this.network);
|
|
95
|
+
if (selected.changeAmount >= BigInt(utils_1.DUST_AMOUNT)) {
|
|
96
|
+
estimator.addOutputAddress(this.address, this.network);
|
|
97
|
+
}
|
|
98
|
+
const newFee = Number(estimator.vsize().value) * feeRate;
|
|
99
|
+
const roundedNewFee = Math.ceil(newFee);
|
|
100
|
+
// Prevent oscillation loops when change falls just below the dust limit.
|
|
101
|
+
// If removing the change output reduces the fee below our budget,
|
|
102
|
+
// we accept the valid transaction state to guarantee convergence.
|
|
103
|
+
if (roundedNewFee <= fee) {
|
|
104
|
+
return { ...selected, fee: roundedNewFee };
|
|
105
|
+
}
|
|
106
|
+
fee = roundedNewFee;
|
|
107
|
+
}
|
|
108
|
+
throw new Error("Fee estimation failed: could not converge");
|
|
109
|
+
}
|
|
62
110
|
async send(params) {
|
|
63
111
|
if (params.amount <= 0) {
|
|
64
112
|
throw new Error("Amount must be positive");
|
|
65
113
|
}
|
|
66
|
-
if (params.amount <
|
|
114
|
+
if (params.amount < utils_1.DUST_AMOUNT) {
|
|
67
115
|
throw new Error("Amount is below dust limit");
|
|
68
116
|
}
|
|
69
117
|
const coins = await this.getCoins();
|
|
@@ -74,15 +122,14 @@ class OnchainWallet {
|
|
|
74
122
|
if (!feeRate || feeRate < OnchainWallet.MIN_FEE_RATE) {
|
|
75
123
|
feeRate = OnchainWallet.MIN_FEE_RATE;
|
|
76
124
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const selected = selectCoins(coins, totalNeeded);
|
|
125
|
+
const { inputs, changeAmount } = this.estimateFeesAndSelectCoins(coins, params.amount, feeRate, params.address);
|
|
126
|
+
if (!inputs) {
|
|
127
|
+
throw new Error("Fee estimation failed");
|
|
128
|
+
}
|
|
82
129
|
// Create transaction
|
|
83
130
|
let tx = new transaction_1.Transaction();
|
|
84
131
|
// Add inputs
|
|
85
|
-
for (const input of
|
|
132
|
+
for (const input of inputs) {
|
|
86
133
|
tx.addInput({
|
|
87
134
|
txid: input.txid,
|
|
88
135
|
index: input.vout,
|
|
@@ -95,9 +142,8 @@ class OnchainWallet {
|
|
|
95
142
|
}
|
|
96
143
|
// Add payment output
|
|
97
144
|
tx.addOutputAddress(params.address, BigInt(params.amount), this.network);
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
tx.addOutputAddress(this.address, selected.changeAmount, this.network);
|
|
145
|
+
if (changeAmount >= BigInt(utils_1.DUST_AMOUNT)) {
|
|
146
|
+
tx.addOutputAddress(this.address, changeAmount, this.network);
|
|
101
147
|
}
|
|
102
148
|
// Sign inputs and Finalize
|
|
103
149
|
tx = await this.identity.sign(tx);
|
|
@@ -116,7 +162,7 @@ class OnchainWallet {
|
|
|
116
162
|
const childVsize = txSizeEstimator_1.TxWeightEstimator.create()
|
|
117
163
|
.addKeySpendInput(true)
|
|
118
164
|
.addP2AInput()
|
|
119
|
-
.
|
|
165
|
+
.addOutputAddress(this.address, this.network)
|
|
120
166
|
.vsize().value;
|
|
121
167
|
const packageVSize = parentVsize + Number(childVsize);
|
|
122
168
|
let feeRate = await this.provider.getFeeRate();
|
|
@@ -160,7 +206,6 @@ class OnchainWallet {
|
|
|
160
206
|
}
|
|
161
207
|
exports.OnchainWallet = OnchainWallet;
|
|
162
208
|
OnchainWallet.MIN_FEE_RATE = 1; // sat/vbyte
|
|
163
|
-
OnchainWallet.DUST_AMOUNT = 546; // sats
|
|
164
209
|
/**
|
|
165
210
|
* Select coins to reach a target amount, prioritizing those closer to expiry
|
|
166
211
|
* @param coins List of coins to select from
|