@1sat/wallet-toolbox 0.0.8 → 0.0.10

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.
Files changed (64) hide show
  1. package/dist/api/balance/index.d.ts +50 -0
  2. package/dist/api/balance/index.js +135 -0
  3. package/dist/api/broadcast/index.d.ts +24 -0
  4. package/dist/api/broadcast/index.js +73 -0
  5. package/dist/api/constants.d.ts +21 -0
  6. package/dist/api/constants.js +29 -0
  7. package/dist/api/index.d.ts +36 -0
  8. package/dist/api/index.js +59 -0
  9. package/dist/api/inscriptions/index.d.ts +25 -0
  10. package/dist/api/inscriptions/index.js +98 -0
  11. package/dist/api/locks/index.d.ts +47 -0
  12. package/dist/api/locks/index.js +291 -0
  13. package/dist/api/ordinals/index.d.ts +102 -0
  14. package/dist/api/ordinals/index.js +566 -0
  15. package/dist/api/payments/index.d.ts +48 -0
  16. package/dist/api/payments/index.js +185 -0
  17. package/dist/api/signing/index.d.ts +35 -0
  18. package/dist/api/signing/index.js +78 -0
  19. package/dist/api/skills/registry.d.ts +61 -0
  20. package/dist/api/skills/registry.js +74 -0
  21. package/dist/api/skills/types.d.ts +71 -0
  22. package/dist/api/skills/types.js +14 -0
  23. package/dist/api/tokens/index.d.ts +87 -0
  24. package/dist/api/tokens/index.js +457 -0
  25. package/dist/cwi/chrome.d.ts +11 -0
  26. package/dist/cwi/chrome.js +39 -0
  27. package/dist/cwi/event.d.ts +11 -0
  28. package/dist/cwi/event.js +38 -0
  29. package/dist/cwi/factory.d.ts +14 -0
  30. package/dist/cwi/factory.js +44 -0
  31. package/dist/cwi/index.d.ts +11 -0
  32. package/dist/cwi/index.js +11 -0
  33. package/dist/cwi/types.d.ts +39 -0
  34. package/dist/cwi/types.js +39 -0
  35. package/dist/index.d.ts +3 -1
  36. package/dist/index.js +7 -1
  37. package/dist/indexers/CosignIndexer.js +1 -0
  38. package/dist/indexers/InscriptionIndexer.js +3 -4
  39. package/dist/indexers/LockIndexer.js +1 -0
  40. package/dist/indexers/OrdLockIndexer.js +1 -0
  41. package/dist/indexers/OriginIndexer.js +1 -1
  42. package/dist/indexers/index.d.ts +1 -1
  43. package/dist/indexers/types.d.ts +18 -0
  44. package/dist/services/OneSatServices.d.ts +19 -10
  45. package/dist/services/OneSatServices.js +201 -39
  46. package/dist/services/client/ChaintracksClient.d.ts +55 -13
  47. package/dist/services/client/ChaintracksClient.js +123 -28
  48. package/dist/services/client/OrdfsClient.d.ts +2 -2
  49. package/dist/services/client/OrdfsClient.js +4 -3
  50. package/dist/services/client/TxoClient.js +9 -0
  51. package/dist/sync/AddressManager.d.ts +85 -0
  52. package/dist/sync/AddressManager.js +107 -0
  53. package/dist/sync/SyncManager.d.ts +207 -0
  54. package/dist/sync/SyncManager.js +507 -0
  55. package/dist/sync/index.d.ts +4 -0
  56. package/dist/sync/index.js +2 -0
  57. package/dist/wallet/factory.d.ts +64 -0
  58. package/dist/wallet/factory.js +129 -0
  59. package/dist/wallet/index.d.ts +1 -0
  60. package/dist/wallet/index.js +1 -0
  61. package/package.json +14 -4
  62. package/dist/OneSatWallet.d.ts +0 -316
  63. package/dist/OneSatWallet.js +0 -956
  64. package/dist/indexers/TransactionParser.d.ts +0 -53
@@ -0,0 +1,291 @@
1
+ /**
2
+ * Locks Module
3
+ *
4
+ * Skills for time-locking BSV.
5
+ */
6
+ import { Hash, PublicKey, Script, Transaction, TransactionSignature, Utils, } from "@bsv/sdk";
7
+ import { LOCK_BASKET, LOCK_PREFIX, LOCK_SUFFIX, MIN_UNLOCK_SATS, WOC_MAINNET_URL, WOC_TESTNET_URL } from "../constants";
8
+ // ============================================================================
9
+ // Constants
10
+ // ============================================================================
11
+ const LOCK_PROTOCOL = [1, "lock"];
12
+ const LOCK_KEY_ID = "lock";
13
+ // ============================================================================
14
+ // Internal helpers
15
+ // ============================================================================
16
+ function buildLockScript(address, until) {
17
+ const pkh = Utils.fromBase58Check(address).data;
18
+ return new Script()
19
+ .writeScript(Script.fromHex(LOCK_PREFIX))
20
+ .writeBin(pkh)
21
+ .writeNumber(until)
22
+ .writeScript(Script.fromHex(LOCK_SUFFIX));
23
+ }
24
+ async function getChainInfoInternal(chain, wocApiKey) {
25
+ const baseUrl = chain === "main" ? WOC_MAINNET_URL : WOC_TESTNET_URL;
26
+ const headers = {};
27
+ if (wocApiKey)
28
+ headers["woc-api-key"] = wocApiKey;
29
+ try {
30
+ const response = await fetch(`${baseUrl}/chain/info`, { headers });
31
+ if (!response.ok)
32
+ return null;
33
+ return await response.json();
34
+ }
35
+ catch {
36
+ return null;
37
+ }
38
+ }
39
+ /**
40
+ * Get lock data summary.
41
+ */
42
+ export const getLockData = {
43
+ meta: {
44
+ name: "getLockData",
45
+ description: "Get summary of time-locked BSV (total, unlockable, next unlock height)",
46
+ category: "locks",
47
+ inputSchema: {
48
+ type: "object",
49
+ properties: {},
50
+ },
51
+ },
52
+ async execute(ctx) {
53
+ const lockData = { totalLocked: 0, unlockable: 0, nextUnlock: 0 };
54
+ const chainInfo = await getChainInfoInternal(ctx.chain, ctx.wocApiKey);
55
+ const currentHeight = chainInfo?.blocks || 0;
56
+ const result = await ctx.wallet.listOutputs({
57
+ basket: LOCK_BASKET,
58
+ includeTags: true,
59
+ limit: 10000,
60
+ });
61
+ const outputs = result.outputs;
62
+ for (const o of outputs) {
63
+ const untilTag = o.tags?.find((t) => t.startsWith("until:"));
64
+ if (!untilTag)
65
+ continue;
66
+ const until = Number.parseInt(untilTag.slice(6), 10);
67
+ lockData.totalLocked += o.satoshis;
68
+ if (until <= currentHeight) {
69
+ lockData.unlockable += o.satoshis;
70
+ }
71
+ else if (!lockData.nextUnlock || until < lockData.nextUnlock) {
72
+ lockData.nextUnlock = until;
73
+ }
74
+ }
75
+ if (lockData.unlockable < MIN_UNLOCK_SATS * outputs.length) {
76
+ lockData.unlockable = 0;
77
+ }
78
+ return lockData;
79
+ },
80
+ };
81
+ /**
82
+ * Lock BSV until a block height.
83
+ */
84
+ export const lockBsv = {
85
+ meta: {
86
+ name: "lockBsv",
87
+ description: "Lock BSV until a specific block height",
88
+ category: "locks",
89
+ inputSchema: {
90
+ type: "object",
91
+ properties: {
92
+ requests: {
93
+ type: "array",
94
+ description: "Array of lock requests",
95
+ items: {
96
+ type: "object",
97
+ properties: {
98
+ satoshis: { type: "integer", description: "Amount in satoshis to lock" },
99
+ until: { type: "integer", description: "Block height until which to lock" },
100
+ },
101
+ required: ["satoshis", "until"],
102
+ },
103
+ },
104
+ },
105
+ required: ["requests"],
106
+ },
107
+ },
108
+ async execute(ctx, input) {
109
+ try {
110
+ const { requests } = input;
111
+ if (!requests || requests.length === 0) {
112
+ return { error: "no-lock-requests" };
113
+ }
114
+ const { publicKey } = await ctx.wallet.getPublicKey({
115
+ protocolID: LOCK_PROTOCOL,
116
+ keyID: LOCK_KEY_ID,
117
+ counterparty: "self",
118
+ forSelf: true,
119
+ });
120
+ const lockAddress = PublicKey.fromString(publicKey).toAddress();
121
+ const outputs = [];
122
+ for (const req of requests) {
123
+ if (req.satoshis <= 0)
124
+ return { error: "invalid-satoshis" };
125
+ if (req.until <= 0)
126
+ return { error: "invalid-block-height" };
127
+ const lockingScript = buildLockScript(lockAddress, req.until);
128
+ outputs.push({
129
+ lockingScript: lockingScript.toHex(),
130
+ satoshis: req.satoshis,
131
+ outputDescription: `Lock ${req.satoshis} sats until block ${req.until}`,
132
+ basket: LOCK_BASKET,
133
+ tags: [`until:${req.until}`],
134
+ customInstructions: JSON.stringify({
135
+ protocolID: LOCK_PROTOCOL,
136
+ keyID: LOCK_KEY_ID,
137
+ }),
138
+ });
139
+ }
140
+ const result = await ctx.wallet.createAction({
141
+ description: `Lock BSV in ${requests.length} output(s)`,
142
+ outputs,
143
+ });
144
+ if (!result.txid) {
145
+ return { error: "no-txid-returned" };
146
+ }
147
+ return { txid: result.txid, rawtx: result.tx ? Utils.toHex(result.tx) : undefined };
148
+ }
149
+ catch (error) {
150
+ return { error: error instanceof Error ? error.message : "unknown-error" };
151
+ }
152
+ },
153
+ };
154
+ /**
155
+ * Unlock matured BSV locks.
156
+ */
157
+ export const unlockBsv = {
158
+ meta: {
159
+ name: "unlockBsv",
160
+ description: "Unlock all matured time-locked BSV",
161
+ category: "locks",
162
+ inputSchema: {
163
+ type: "object",
164
+ properties: {},
165
+ },
166
+ },
167
+ async execute(ctx) {
168
+ try {
169
+ const chainInfo = await getChainInfoInternal(ctx.chain, ctx.wocApiKey);
170
+ const currentHeight = chainInfo?.blocks || 0;
171
+ if (currentHeight === 0) {
172
+ return { error: "could-not-get-block-height" };
173
+ }
174
+ const result = await ctx.wallet.listOutputs({
175
+ basket: LOCK_BASKET,
176
+ includeTags: true,
177
+ includeCustomInstructions: true,
178
+ include: "locking scripts",
179
+ limit: 10000,
180
+ });
181
+ const maturedLocks = [];
182
+ for (const o of result.outputs) {
183
+ const untilTag = o.tags?.find((t) => t.startsWith("until:"));
184
+ if (!untilTag)
185
+ continue;
186
+ const until = Number.parseInt(untilTag.slice(6), 10);
187
+ let protocolID = LOCK_PROTOCOL;
188
+ let keyID = LOCK_KEY_ID;
189
+ if (o.customInstructions) {
190
+ const instructions = JSON.parse(o.customInstructions);
191
+ protocolID = instructions.protocolID ?? LOCK_PROTOCOL;
192
+ keyID = instructions.keyID ?? LOCK_KEY_ID;
193
+ }
194
+ if (until <= currentHeight) {
195
+ maturedLocks.push({ output: o, until, protocolID, keyID });
196
+ }
197
+ }
198
+ if (maturedLocks.length === 0) {
199
+ return { error: "no-matured-locks" };
200
+ }
201
+ const totalSats = maturedLocks.reduce((sum, l) => sum + l.output.satoshis, 0);
202
+ if (totalSats < MIN_UNLOCK_SATS * maturedLocks.length) {
203
+ return { error: "insufficient-unlock-amount" };
204
+ }
205
+ const maxUntil = Math.max(...maturedLocks.map((l) => l.until));
206
+ const createResult = await ctx.wallet.createAction({
207
+ description: `Unlock ${maturedLocks.length} lock(s)`,
208
+ inputs: maturedLocks.map((l) => ({
209
+ outpoint: l.output.outpoint,
210
+ inputDescription: "Locked BSV",
211
+ unlockingScriptLength: 180,
212
+ sequenceNumber: 0,
213
+ })),
214
+ outputs: [
215
+ {
216
+ lockingScript: "",
217
+ satoshis: 0,
218
+ outputDescription: "Unlocked BSV",
219
+ },
220
+ ],
221
+ lockTime: maxUntil,
222
+ options: { signAndProcess: false },
223
+ });
224
+ if ("error" in createResult && createResult.error) {
225
+ return { error: String(createResult.error) };
226
+ }
227
+ if (!createResult.signableTransaction) {
228
+ return { error: "no-signable-transaction" };
229
+ }
230
+ const tx = Transaction.fromBEEF(createResult.signableTransaction.tx);
231
+ const spends = {};
232
+ for (let i = 0; i < maturedLocks.length; i++) {
233
+ const lock = maturedLocks[i];
234
+ const input = tx.inputs[i];
235
+ const lockingScript = Script.fromHex(lock.output.lockingScript);
236
+ const preimage = TransactionSignature.format({
237
+ sourceTXID: input.sourceTXID,
238
+ sourceOutputIndex: input.sourceOutputIndex,
239
+ sourceSatoshis: lock.output.satoshis,
240
+ transactionVersion: tx.version,
241
+ otherInputs: tx.inputs.filter((_, idx) => idx !== i),
242
+ outputs: tx.outputs,
243
+ inputIndex: i,
244
+ subscript: lockingScript,
245
+ inputSequence: 0,
246
+ lockTime: tx.lockTime,
247
+ scope: TransactionSignature.SIGHASH_ALL |
248
+ TransactionSignature.SIGHASH_ANYONECANPAY |
249
+ TransactionSignature.SIGHASH_FORKID,
250
+ });
251
+ const sighash = Hash.sha256(Hash.sha256(preimage));
252
+ const { signature } = await ctx.wallet.createSignature({
253
+ protocolID: lock.protocolID,
254
+ keyID: lock.keyID,
255
+ counterparty: "self",
256
+ hashToDirectlySign: Array.from(sighash),
257
+ });
258
+ const { publicKey } = await ctx.wallet.getPublicKey({
259
+ protocolID: lock.protocolID,
260
+ keyID: lock.keyID,
261
+ counterparty: "self",
262
+ forSelf: true,
263
+ });
264
+ const unlockingScript = new Script()
265
+ .writeBin(signature)
266
+ .writeBin(Utils.toArray(publicKey, "hex"))
267
+ .writeBin(Array.from(preimage));
268
+ spends[i] = { unlockingScript: unlockingScript.toHex() };
269
+ }
270
+ const signResult = await ctx.wallet.signAction({
271
+ reference: createResult.signableTransaction.reference,
272
+ spends,
273
+ });
274
+ if ("error" in signResult) {
275
+ return { error: String(signResult.error) };
276
+ }
277
+ return {
278
+ txid: signResult.txid,
279
+ rawtx: signResult.tx ? Utils.toHex(signResult.tx) : undefined,
280
+ };
281
+ }
282
+ catch (error) {
283
+ return { error: error instanceof Error ? error.message : "unknown-error" };
284
+ }
285
+ },
286
+ };
287
+ // ============================================================================
288
+ // Module exports
289
+ // ============================================================================
290
+ /** All lock skills for registry */
291
+ export const locksSkills = [getLockData, lockBsv, unlockBsv];
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Ordinals Module
3
+ *
4
+ * Skills for managing ordinals/inscriptions.
5
+ * Returns WalletOutput[] directly from the SDK - no custom mapping needed.
6
+ */
7
+ import { type WalletOutput, type CreateActionArgs } from "@bsv/sdk";
8
+ import type { Skill, OneSatContext } from "../skills/types";
9
+ type PubKeyHex = string;
10
+ export interface TransferOrdinalRequest {
11
+ /** Outpoint of the ordinal to transfer (txid_vout format) */
12
+ outpoint: string;
13
+ /** Recipient's identity public key (preferred) */
14
+ counterparty?: PubKeyHex;
15
+ /** Legacy: raw P2PKH address */
16
+ address?: string;
17
+ /** Paymail address */
18
+ paymail?: string;
19
+ }
20
+ export interface ListOrdinalRequest {
21
+ /** Outpoint of ordinal to list */
22
+ outpoint: string;
23
+ /** Price in satoshis */
24
+ price: number;
25
+ /** Address that receives payment on purchase (BRC-29 receive address) */
26
+ payAddress: string;
27
+ }
28
+ export interface PurchaseOrdinalRequest {
29
+ /** Outpoint of listing to purchase */
30
+ outpoint: string;
31
+ /** Marketplace address for fees */
32
+ marketplaceAddress?: string;
33
+ /** Marketplace fee rate (0-1) */
34
+ marketplaceRate?: number;
35
+ /** Optional content type - looked up from ordfs API if not provided */
36
+ contentType?: string;
37
+ /** Optional origin outpoint - looked up from ordfs API if not provided */
38
+ origin?: string;
39
+ }
40
+ export interface OrdinalOperationResponse {
41
+ txid?: string;
42
+ rawtx?: string;
43
+ error?: string;
44
+ }
45
+ /**
46
+ * Build CreateActionArgs for transferring an ordinal.
47
+ * Does NOT execute - returns params for createAction.
48
+ */
49
+ export declare function buildTransferOrdinal(ctx: OneSatContext, request: TransferOrdinalRequest): Promise<CreateActionArgs | {
50
+ error: string;
51
+ }>;
52
+ /**
53
+ * Build CreateActionArgs for listing an ordinal for sale.
54
+ * Does NOT execute - returns params for createAction.
55
+ */
56
+ export declare function buildListOrdinal(ctx: OneSatContext, request: ListOrdinalRequest): Promise<CreateActionArgs | {
57
+ error: string;
58
+ }>;
59
+ /** Input for listOrdinals skill */
60
+ export interface ListOrdinalsInput {
61
+ /** Max number of ordinals to return */
62
+ limit?: number;
63
+ /** Offset for pagination */
64
+ offset?: number;
65
+ }
66
+ /**
67
+ * List ordinals from the wallet.
68
+ */
69
+ export declare const listOrdinals: Skill<ListOrdinalsInput, WalletOutput[]>;
70
+ /** Input for deriveCancelAddress skill */
71
+ export interface DeriveCancelAddressInput {
72
+ /** Outpoint of the ordinal listing */
73
+ outpoint: string;
74
+ }
75
+ /**
76
+ * Derive a cancel address for an ordinal listing.
77
+ */
78
+ export declare const deriveCancelAddress: Skill<DeriveCancelAddressInput, string>;
79
+ /**
80
+ * Transfer an ordinal to a new owner.
81
+ */
82
+ export declare const transferOrdinal: Skill<TransferOrdinalRequest, OrdinalOperationResponse>;
83
+ /**
84
+ * List an ordinal for sale on the global orderbook.
85
+ */
86
+ export declare const listOrdinal: Skill<ListOrdinalRequest, OrdinalOperationResponse>;
87
+ /** Input for cancelListing skill */
88
+ export interface CancelListingInput {
89
+ /** Outpoint of the listing to cancel */
90
+ outpoint: string;
91
+ }
92
+ /**
93
+ * Cancel an ordinal listing.
94
+ */
95
+ export declare const cancelListing: Skill<CancelListingInput, OrdinalOperationResponse>;
96
+ /**
97
+ * Purchase an ordinal from the global orderbook.
98
+ */
99
+ export declare const purchaseOrdinal: Skill<PurchaseOrdinalRequest, OrdinalOperationResponse>;
100
+ /** All ordinals skills for registry */
101
+ export declare const ordinalsSkills: (Skill<ListOrdinalsInput, WalletOutput[]> | Skill<DeriveCancelAddressInput, string> | Skill<TransferOrdinalRequest, OrdinalOperationResponse> | Skill<ListOrdinalRequest, OrdinalOperationResponse> | Skill<PurchaseOrdinalRequest, OrdinalOperationResponse>)[];
102
+ export {};