digirails 0.1.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.
Files changed (135) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +102 -0
  3. package/dist/agent.d.ts +72 -0
  4. package/dist/agent.d.ts.map +1 -0
  5. package/dist/agent.js +176 -0
  6. package/dist/agent.js.map +1 -0
  7. package/dist/config.d.ts +24 -0
  8. package/dist/config.d.ts.map +1 -0
  9. package/dist/config.js +46 -0
  10. package/dist/config.js.map +1 -0
  11. package/dist/crypto/base58.d.ts +9 -0
  12. package/dist/crypto/base58.d.ts.map +1 -0
  13. package/dist/crypto/base58.js +107 -0
  14. package/dist/crypto/base58.js.map +1 -0
  15. package/dist/crypto/bech32.d.ts +9 -0
  16. package/dist/crypto/bech32.d.ts.map +1 -0
  17. package/dist/crypto/bech32.js +141 -0
  18. package/dist/crypto/bech32.js.map +1 -0
  19. package/dist/crypto/index.d.ts +6 -0
  20. package/dist/crypto/index.d.ts.map +1 -0
  21. package/dist/crypto/index.js +22 -0
  22. package/dist/crypto/index.js.map +1 -0
  23. package/dist/crypto/keys.d.ts +25 -0
  24. package/dist/crypto/keys.d.ts.map +1 -0
  25. package/dist/crypto/keys.js +129 -0
  26. package/dist/crypto/keys.js.map +1 -0
  27. package/dist/crypto/script.d.ts +12 -0
  28. package/dist/crypto/script.d.ts.map +1 -0
  29. package/dist/crypto/script.js +105 -0
  30. package/dist/crypto/script.js.map +1 -0
  31. package/dist/crypto/transaction.d.ts +47 -0
  32. package/dist/crypto/transaction.d.ts.map +1 -0
  33. package/dist/crypto/transaction.js +227 -0
  34. package/dist/crypto/transaction.js.map +1 -0
  35. package/dist/discovery/index.d.ts +2 -0
  36. package/dist/discovery/index.d.ts.map +1 -0
  37. package/dist/discovery/index.js +6 -0
  38. package/dist/discovery/index.js.map +1 -0
  39. package/dist/discovery/manifest_client.d.ts +9 -0
  40. package/dist/discovery/manifest_client.d.ts.map +1 -0
  41. package/dist/discovery/manifest_client.js +29 -0
  42. package/dist/discovery/manifest_client.js.map +1 -0
  43. package/dist/exceptions.d.ts +32 -0
  44. package/dist/exceptions.d.ts.map +1 -0
  45. package/dist/exceptions.js +72 -0
  46. package/dist/exceptions.js.map +1 -0
  47. package/dist/index.d.ts +31 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +135 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/models/enums.d.ts +48 -0
  52. package/dist/models/enums.d.ts.map +1 -0
  53. package/dist/models/enums.js +84 -0
  54. package/dist/models/enums.js.map +1 -0
  55. package/dist/models/index.d.ts +4 -0
  56. package/dist/models/index.d.ts.map +1 -0
  57. package/dist/models/index.js +20 -0
  58. package/dist/models/index.js.map +1 -0
  59. package/dist/models/manifest.d.ts +327 -0
  60. package/dist/models/manifest.d.ts.map +1 -0
  61. package/dist/models/manifest.js +47 -0
  62. package/dist/models/manifest.js.map +1 -0
  63. package/dist/models/messages.d.ts +336 -0
  64. package/dist/models/messages.d.ts.map +1 -0
  65. package/dist/models/messages.js +166 -0
  66. package/dist/models/messages.js.map +1 -0
  67. package/dist/network/constants.d.ts +51 -0
  68. package/dist/network/constants.d.ts.map +1 -0
  69. package/dist/network/constants.js +63 -0
  70. package/dist/network/constants.js.map +1 -0
  71. package/dist/network/index.d.ts +3 -0
  72. package/dist/network/index.d.ts.map +1 -0
  73. package/dist/network/index.js +19 -0
  74. package/dist/network/index.js.map +1 -0
  75. package/dist/network/params.d.ts +21 -0
  76. package/dist/network/params.d.ts.map +1 -0
  77. package/dist/network/params.js +57 -0
  78. package/dist/network/params.js.map +1 -0
  79. package/dist/opreturn.d.ts +25 -0
  80. package/dist/opreturn.d.ts.map +1 -0
  81. package/dist/opreturn.js +118 -0
  82. package/dist/opreturn.js.map +1 -0
  83. package/dist/payment/buyer.d.ts +29 -0
  84. package/dist/payment/buyer.d.ts.map +1 -0
  85. package/dist/payment/buyer.js +118 -0
  86. package/dist/payment/buyer.js.map +1 -0
  87. package/dist/payment/flow.d.ts +20 -0
  88. package/dist/payment/flow.d.ts.map +1 -0
  89. package/dist/payment/flow.js +29 -0
  90. package/dist/payment/flow.js.map +1 -0
  91. package/dist/payment/index.d.ts +5 -0
  92. package/dist/payment/index.d.ts.map +1 -0
  93. package/dist/payment/index.js +13 -0
  94. package/dist/payment/index.js.map +1 -0
  95. package/dist/payment/seller.d.ts +27 -0
  96. package/dist/payment/seller.d.ts.map +1 -0
  97. package/dist/payment/seller.js +193 -0
  98. package/dist/payment/seller.js.map +1 -0
  99. package/dist/payment/verification.d.ts +8 -0
  100. package/dist/payment/verification.d.ts.map +1 -0
  101. package/dist/payment/verification.js +89 -0
  102. package/dist/payment/verification.js.map +1 -0
  103. package/dist/rpc/client.d.ts +21 -0
  104. package/dist/rpc/client.d.ts.map +1 -0
  105. package/dist/rpc/client.js +131 -0
  106. package/dist/rpc/client.js.map +1 -0
  107. package/dist/rpc/index.d.ts +2 -0
  108. package/dist/rpc/index.d.ts.map +1 -0
  109. package/dist/rpc/index.js +6 -0
  110. package/dist/rpc/index.js.map +1 -0
  111. package/dist/server.d.ts +24 -0
  112. package/dist/server.d.ts.map +1 -0
  113. package/dist/server.js +104 -0
  114. package/dist/server.js.map +1 -0
  115. package/dist/version.d.ts +2 -0
  116. package/dist/version.d.ts.map +1 -0
  117. package/dist/version.js +5 -0
  118. package/dist/version.js.map +1 -0
  119. package/dist/wallet/index.d.ts +4 -0
  120. package/dist/wallet/index.d.ts.map +1 -0
  121. package/dist/wallet/index.js +14 -0
  122. package/dist/wallet/index.js.map +1 -0
  123. package/dist/wallet/keystore.d.ts +32 -0
  124. package/dist/wallet/keystore.d.ts.map +1 -0
  125. package/dist/wallet/keystore.js +111 -0
  126. package/dist/wallet/keystore.js.map +1 -0
  127. package/dist/wallet/utxo.d.ts +32 -0
  128. package/dist/wallet/utxo.d.ts.map +1 -0
  129. package/dist/wallet/utxo.js +88 -0
  130. package/dist/wallet/utxo.js.map +1 -0
  131. package/dist/wallet/wallet.d.ts +52 -0
  132. package/dist/wallet/wallet.d.ts.map +1 -0
  133. package/dist/wallet/wallet.js +249 -0
  134. package/dist/wallet/wallet.js.map +1 -0
  135. package/package.json +43 -0
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VERSION = void 0;
4
+ exports.VERSION = '0.1.0';
5
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":";;;AAAa,QAAA,OAAO,GAAG,OAAO,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { Wallet } from './wallet';
2
+ export { UtxoSet, Utxo, satToDgb, dgbToSat } from './utxo';
3
+ export { Keystore, EncryptedKeystore, EnvKeystore, RawKeystore } from './keystore';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/wallet/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RawKeystore = exports.EnvKeystore = exports.EncryptedKeystore = exports.dgbToSat = exports.satToDgb = exports.UtxoSet = exports.Wallet = void 0;
4
+ var wallet_1 = require("./wallet");
5
+ Object.defineProperty(exports, "Wallet", { enumerable: true, get: function () { return wallet_1.Wallet; } });
6
+ var utxo_1 = require("./utxo");
7
+ Object.defineProperty(exports, "UtxoSet", { enumerable: true, get: function () { return utxo_1.UtxoSet; } });
8
+ Object.defineProperty(exports, "satToDgb", { enumerable: true, get: function () { return utxo_1.satToDgb; } });
9
+ Object.defineProperty(exports, "dgbToSat", { enumerable: true, get: function () { return utxo_1.dgbToSat; } });
10
+ var keystore_1 = require("./keystore");
11
+ Object.defineProperty(exports, "EncryptedKeystore", { enumerable: true, get: function () { return keystore_1.EncryptedKeystore; } });
12
+ Object.defineProperty(exports, "EnvKeystore", { enumerable: true, get: function () { return keystore_1.EnvKeystore; } });
13
+ Object.defineProperty(exports, "RawKeystore", { enumerable: true, get: function () { return keystore_1.RawKeystore; } });
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/wallet/index.ts"],"names":[],"mappings":";;;AAAA,mCAAkC;AAAzB,gGAAA,MAAM,OAAA;AACf,+BAA2D;AAAlD,+FAAA,OAAO,OAAA;AAAQ,gGAAA,QAAQ,OAAA;AAAE,gGAAA,QAAQ,OAAA;AAC1C,uCAAmF;AAAhE,6GAAA,iBAAiB,OAAA;AAAE,uGAAA,WAAW,OAAA;AAAE,uGAAA,WAAW,OAAA"}
@@ -0,0 +1,32 @@
1
+ /** Abstract keystore interface */
2
+ export interface Keystore {
3
+ load(): Buffer;
4
+ save(privateKey: Buffer): void;
5
+ }
6
+ /**
7
+ * AES-256-GCM encrypted keystore with PBKDF2 key derivation.
8
+ * File format: salt(16B) + nonce(12B) + ciphertext + authTag(16B)
9
+ */
10
+ export declare class EncryptedKeystore implements Keystore {
11
+ private path;
12
+ private password;
13
+ private iterations;
14
+ constructor(path: string, password: string, iterations?: number);
15
+ load(): Buffer;
16
+ save(privateKey: Buffer): void;
17
+ }
18
+ /** Read private key from an environment variable (hex-encoded) */
19
+ export declare class EnvKeystore implements Keystore {
20
+ private envVar;
21
+ constructor(envVar?: string);
22
+ load(): Buffer;
23
+ save(_privateKey: Buffer): void;
24
+ }
25
+ /** In-memory keystore for testing */
26
+ export declare class RawKeystore implements Keystore {
27
+ private key;
28
+ constructor(key?: Buffer);
29
+ load(): Buffer;
30
+ save(privateKey: Buffer): void;
31
+ }
32
+ //# sourceMappingURL=keystore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keystore.d.ts","sourceRoot":"","sources":["../../src/wallet/keystore.ts"],"names":[],"mappings":"AAOA,kCAAkC;AAClC,MAAM,WAAW,QAAQ;IACvB,IAAI,IAAI,MAAM,CAAC;IACf,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED;;;GAGG;AACH,qBAAa,iBAAkB,YAAW,QAAQ;IAChD,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAS;gBAEf,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,SAAU;IAMhE,IAAI,IAAI,MAAM;IAmCd,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;CAgB/B;AAED,kEAAkE;AAClE,qBAAa,WAAY,YAAW,QAAQ;IAC1C,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,SAA0B;IAI5C,IAAI,IAAI,MAAM;IAcd,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;CAGhC;AAED,qCAAqC;AACrC,qBAAa,WAAY,YAAW,QAAQ;IAC1C,OAAO,CAAC,GAAG,CAAgB;gBAEf,GAAG,CAAC,EAAE,MAAM;IAIxB,IAAI,IAAI,MAAM;IAUd,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;CAG/B"}
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RawKeystore = exports.EnvKeystore = exports.EncryptedKeystore = void 0;
4
+ /**
5
+ * Key storage backends: encrypted file, environment variable, and raw (testing).
6
+ */
7
+ const crypto_1 = require("crypto");
8
+ const fs_1 = require("fs");
9
+ const exceptions_1 = require("../exceptions");
10
+ /**
11
+ * AES-256-GCM encrypted keystore with PBKDF2 key derivation.
12
+ * File format: salt(16B) + nonce(12B) + ciphertext + authTag(16B)
13
+ */
14
+ class EncryptedKeystore {
15
+ path;
16
+ password;
17
+ iterations;
18
+ constructor(path, password, iterations = 600_000) {
19
+ this.path = path;
20
+ this.password = password;
21
+ this.iterations = iterations;
22
+ }
23
+ load() {
24
+ let data;
25
+ try {
26
+ data = (0, fs_1.readFileSync)(this.path);
27
+ }
28
+ catch (err) {
29
+ throw new exceptions_1.KeystoreError(`Cannot read keystore: ${err.message}`);
30
+ }
31
+ if (data.length < 44) {
32
+ throw new exceptions_1.KeystoreError('Keystore file too short');
33
+ }
34
+ const salt = data.slice(0, 16);
35
+ const nonce = data.slice(16, 28);
36
+ const authTag = data.slice(data.length - 16);
37
+ const ciphertext = data.slice(28, data.length - 16);
38
+ const key = (0, crypto_1.pbkdf2Sync)(this.password, salt, this.iterations, 32, 'sha256');
39
+ try {
40
+ const decipher = (0, crypto_1.createDecipheriv)('aes-256-gcm', key, nonce);
41
+ decipher.setAuthTag(authTag);
42
+ const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
43
+ if (decrypted.length !== 32) {
44
+ throw new exceptions_1.KeystoreError(`Invalid key length after decryption: ${decrypted.length}`);
45
+ }
46
+ return decrypted;
47
+ }
48
+ catch (err) {
49
+ if (err instanceof exceptions_1.KeystoreError)
50
+ throw err;
51
+ throw new exceptions_1.KeystoreError('Decryption failed (wrong password?)');
52
+ }
53
+ }
54
+ save(privateKey) {
55
+ if (privateKey.length !== 32) {
56
+ throw new exceptions_1.KeystoreError(`Private key must be 32 bytes, got ${privateKey.length}`);
57
+ }
58
+ const salt = (0, crypto_1.randomBytes)(16);
59
+ const nonce = (0, crypto_1.randomBytes)(12);
60
+ const key = (0, crypto_1.pbkdf2Sync)(this.password, salt, this.iterations, 32, 'sha256');
61
+ const cipher = (0, crypto_1.createCipheriv)('aes-256-gcm', key, nonce);
62
+ const ciphertext = Buffer.concat([cipher.update(privateKey), cipher.final()]);
63
+ const authTag = cipher.getAuthTag();
64
+ const output = Buffer.concat([salt, nonce, ciphertext, authTag]);
65
+ (0, fs_1.writeFileSync)(this.path, output);
66
+ }
67
+ }
68
+ exports.EncryptedKeystore = EncryptedKeystore;
69
+ /** Read private key from an environment variable (hex-encoded) */
70
+ class EnvKeystore {
71
+ envVar;
72
+ constructor(envVar = 'DIGIRAILS_PRIVATE_KEY') {
73
+ this.envVar = envVar;
74
+ }
75
+ load() {
76
+ const value = process.env[this.envVar];
77
+ if (!value) {
78
+ throw new exceptions_1.KeystoreError(`Environment variable ${this.envVar} not set`);
79
+ }
80
+ const key = Buffer.from(value, 'hex');
81
+ if (key.length !== 32) {
82
+ throw new exceptions_1.KeystoreError(`Invalid key length from ${this.envVar}: ${key.length}`);
83
+ }
84
+ return key;
85
+ }
86
+ save(_privateKey) {
87
+ throw new exceptions_1.KeystoreError('EnvKeystore does not support save()');
88
+ }
89
+ }
90
+ exports.EnvKeystore = EnvKeystore;
91
+ /** In-memory keystore for testing */
92
+ class RawKeystore {
93
+ key;
94
+ constructor(key) {
95
+ this.key = key ?? null;
96
+ }
97
+ load() {
98
+ if (!this.key) {
99
+ throw new exceptions_1.KeystoreError('No key stored');
100
+ }
101
+ if (this.key.length !== 32) {
102
+ throw new exceptions_1.KeystoreError(`Invalid key length: ${this.key.length}`);
103
+ }
104
+ return this.key;
105
+ }
106
+ save(privateKey) {
107
+ this.key = Buffer.from(privateKey);
108
+ }
109
+ }
110
+ exports.RawKeystore = RawKeystore;
111
+ //# sourceMappingURL=keystore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keystore.js","sourceRoot":"","sources":["../../src/wallet/keystore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ export interface Utxo {
2
+ txid: string;
3
+ vout: number;
4
+ amountSat: bigint;
5
+ scriptPubkey: Buffer;
6
+ confirmations: number;
7
+ }
8
+ export declare class UtxoSet {
9
+ private utxos;
10
+ private key;
11
+ add(utxo: Utxo): void;
12
+ remove(txid: string, vout: number): boolean;
13
+ get(txid: string, vout: number): Utxo | undefined;
14
+ get size(): number;
15
+ /** Total satoshis across all UTXOs */
16
+ get totalSat(): bigint;
17
+ /** Total DGB as string (8 decimal places) */
18
+ get totalDgb(): string;
19
+ /** All UTXOs as array */
20
+ all(): Utxo[];
21
+ /**
22
+ * Select UTXOs to meet target amount. Uses largest-first greedy strategy.
23
+ * Returns selected UTXOs or throws InsufficientFundsError.
24
+ */
25
+ select(targetSat: bigint): Utxo[];
26
+ clear(): void;
27
+ }
28
+ /** Convert satoshis to DGB string (8 decimal places) */
29
+ export declare function satToDgb(sat: bigint): string;
30
+ /** Convert DGB string to satoshis */
31
+ export declare function dgbToSat(dgb: string): bigint;
32
+ //# sourceMappingURL=utxo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utxo.d.ts","sourceRoot":"","sources":["../../src/wallet/utxo.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,qBAAa,OAAO;IAClB,OAAO,CAAC,KAAK,CAAgC;IAE7C,OAAO,CAAC,GAAG;IAIX,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAIrB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO;IAI3C,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS;IAIjD,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,sCAAsC;IACtC,IAAI,QAAQ,IAAI,MAAM,CAMrB;IAED,6CAA6C;IAC7C,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,yBAAyB;IACzB,GAAG,IAAI,IAAI,EAAE;IAIb;;;OAGG;IACH,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,EAAE;IAuBjC,KAAK,IAAI,IAAI;CAGd;AAED,wDAAwD;AACxD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAK5C;AAED,qCAAqC;AACrC,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAO5C"}
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UtxoSet = void 0;
4
+ exports.satToDgb = satToDgb;
5
+ exports.dgbToSat = dgbToSat;
6
+ /**
7
+ * UTXO tracking and coin selection.
8
+ */
9
+ const constants_1 = require("../network/constants");
10
+ const exceptions_1 = require("../exceptions");
11
+ class UtxoSet {
12
+ utxos = new Map();
13
+ key(txid, vout) {
14
+ return `${txid}:${vout}`;
15
+ }
16
+ add(utxo) {
17
+ this.utxos.set(this.key(utxo.txid, utxo.vout), utxo);
18
+ }
19
+ remove(txid, vout) {
20
+ return this.utxos.delete(this.key(txid, vout));
21
+ }
22
+ get(txid, vout) {
23
+ return this.utxos.get(this.key(txid, vout));
24
+ }
25
+ get size() {
26
+ return this.utxos.size;
27
+ }
28
+ /** Total satoshis across all UTXOs */
29
+ get totalSat() {
30
+ let total = 0n;
31
+ for (const utxo of this.utxos.values()) {
32
+ total += utxo.amountSat;
33
+ }
34
+ return total;
35
+ }
36
+ /** Total DGB as string (8 decimal places) */
37
+ get totalDgb() {
38
+ return satToDgb(this.totalSat);
39
+ }
40
+ /** All UTXOs as array */
41
+ all() {
42
+ return Array.from(this.utxos.values());
43
+ }
44
+ /**
45
+ * Select UTXOs to meet target amount. Uses largest-first greedy strategy.
46
+ * Returns selected UTXOs or throws InsufficientFundsError.
47
+ */
48
+ select(targetSat) {
49
+ const sorted = this.all().sort((a, b) => {
50
+ if (a.amountSat > b.amountSat)
51
+ return -1;
52
+ if (a.amountSat < b.amountSat)
53
+ return 1;
54
+ return 0;
55
+ });
56
+ const selected = [];
57
+ let accumulated = 0n;
58
+ for (const utxo of sorted) {
59
+ selected.push(utxo);
60
+ accumulated += utxo.amountSat;
61
+ if (accumulated >= targetSat) {
62
+ return selected;
63
+ }
64
+ }
65
+ throw new exceptions_1.InsufficientFundsError(`Insufficient funds: have ${accumulated} sat, need ${targetSat} sat`);
66
+ }
67
+ clear() {
68
+ this.utxos.clear();
69
+ }
70
+ }
71
+ exports.UtxoSet = UtxoSet;
72
+ /** Convert satoshis to DGB string (8 decimal places) */
73
+ function satToDgb(sat) {
74
+ const whole = sat / constants_1.SATOSHIS_PER_DGB;
75
+ const frac = sat % constants_1.SATOSHIS_PER_DGB;
76
+ const fracStr = frac.toString().padStart(8, '0');
77
+ return `${whole}.${fracStr}`;
78
+ }
79
+ /** Convert DGB string to satoshis */
80
+ function dgbToSat(dgb) {
81
+ const parts = dgb.split('.');
82
+ const whole = BigInt(parts[0]) * constants_1.SATOSHIS_PER_DGB;
83
+ if (parts.length === 1)
84
+ return whole;
85
+ const fracStr = parts[1].padEnd(8, '0').slice(0, 8);
86
+ return whole + BigInt(fracStr);
87
+ }
88
+ //# sourceMappingURL=utxo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utxo.js","sourceRoot":"","sources":["../../src/wallet/utxo.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import { Transaction } from '../crypto/transaction';
2
+ import { RpcClient } from '../rpc/client';
3
+ import { UtxoSet, Utxo } from './utxo';
4
+ import { NetworkParams } from '../network/params';
5
+ export declare class Wallet {
6
+ private privateKey;
7
+ private pubkey;
8
+ private _address;
9
+ private _scriptPubkey;
10
+ private _utxoSet;
11
+ private rpc;
12
+ private network;
13
+ private _uncommitted;
14
+ constructor(privateKey: Buffer, network?: NetworkParams, rpc?: RpcClient);
15
+ get address(): string;
16
+ get publicKey(): Buffer;
17
+ get scriptPubkey(): Buffer;
18
+ get utxoSet(): UtxoSet;
19
+ /** The network this wallet operates on */
20
+ getNetwork(): NetworkParams;
21
+ /** Returns the primary address (Phase 1: single address, no HD) */
22
+ freshAddress(): string;
23
+ /** Sync UTXOs from RPC, filtered by pending spend tracker. */
24
+ syncUtxos(): Promise<void>;
25
+ /** Manually add a UTXO */
26
+ addUtxo(utxo: Utxo): void;
27
+ /** Mark a UTXO as spent */
28
+ spendUtxo(txid: string, vout: number): void;
29
+ /** Get balance in DGB string */
30
+ balance(): Promise<string>;
31
+ /**
32
+ * Build a signed payment transaction.
33
+ *
34
+ * Marks UTXOs as spent locally but defers module-level tracking to
35
+ * broadcast() so a failed RPC call can roll back cleanly.
36
+ */
37
+ buildPayment(params: {
38
+ toAddress: string;
39
+ amountSat: bigint;
40
+ feeSat?: bigint;
41
+ opReturnData?: Uint8Array;
42
+ }): Promise<Transaction>;
43
+ /**
44
+ * Broadcast a signed transaction. Returns txid.
45
+ *
46
+ * On success, commits spend info to the module-level pending tracker
47
+ * so other Wallet instances (same process) see the spent outpoints.
48
+ * On failure, rolls back local UTXO state so the wallet can retry.
49
+ */
50
+ broadcast(tx: Transaction): Promise<string>;
51
+ }
52
+ //# sourceMappingURL=wallet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wallet.d.ts","sourceRoot":"","sources":["../../src/wallet/wallet.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,WAAW,EAA2B,MAAM,uBAAuB,CAAC;AAC7E,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAsB,MAAM,QAAQ,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAW,MAAM,mBAAmB,CAAC;AAgF3D,qBAAa,MAAM;IACjB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAU;IAC1B,OAAO,CAAC,GAAG,CAAmB;IAC9B,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,YAAY,CAA4B;gBAG9C,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,aAAuB,EAChC,GAAG,CAAC,EAAE,SAAS;IAYjB,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,0CAA0C;IAC1C,UAAU,IAAI,aAAa;IAI3B,mEAAmE;IACnE,YAAY,IAAI,MAAM;IAItB,8DAA8D;IACxD,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IA4BhC,0BAA0B;IAC1B,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAIzB,2BAA2B;IAC3B,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAI3C,gCAAgC;IAC1B,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;IAOhC;;;;;OAKG;IACG,YAAY,CAAC,MAAM,EAAE;QACzB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,YAAY,CAAC,EAAE,UAAU,CAAC;KAC3B,GAAG,OAAO,CAAC,WAAW,CAAC;IA0ExB;;;;;;OAMG;IACG,SAAS,CAAC,EAAE,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;CAmClD"}
@@ -0,0 +1,249 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Wallet = void 0;
4
+ /**
5
+ * Single-key wallet for DigiByte payments.
6
+ */
7
+ const keys_1 = require("../crypto/keys");
8
+ const script_1 = require("../crypto/script");
9
+ const transaction_1 = require("../crypto/transaction");
10
+ const utxo_1 = require("./utxo");
11
+ const params_1 = require("../network/params");
12
+ // ---------------------------------------------------------------------------
13
+ // Module-level pending spend tracker
14
+ // ---------------------------------------------------------------------------
15
+ // Persists across Wallet instances within a process. Prevents double-spending
16
+ // when the same address is used by multiple short-lived Agent instances
17
+ // (e.g. chaos testing, rapid-fire buyer flows).
18
+ // ---------------------------------------------------------------------------
19
+ const PENDING_TTL = 120_000; // 120 seconds in ms
20
+ class PendingTracker {
21
+ spent = new Map(); // "txid:vout" -> expiresAt
22
+ change = new Map(); // "txid:vout" -> {utxo, expiresAt}
23
+ key(txid, vout) {
24
+ return `${txid}:${vout}`;
25
+ }
26
+ recordSpend(spentOutpoints, changeUtxo) {
27
+ const expiresAt = Date.now() + PENDING_TTL;
28
+ for (const op of spentOutpoints) {
29
+ this.spent.set(this.key(op.txid, op.vout), expiresAt);
30
+ }
31
+ if (changeUtxo) {
32
+ const k = this.key(changeUtxo.txid, changeUtxo.vout);
33
+ this.change.set(k, { utxo: changeUtxo, expiresAt });
34
+ }
35
+ this.purge();
36
+ }
37
+ apply(utxos, scriptPubkey) {
38
+ this.purge();
39
+ // Remove anything recently spent
40
+ const filtered = utxos.filter((u) => !this.spent.has(this.key(u.txid, u.vout)));
41
+ // Inject pending change outputs
42
+ const existing = new Set(filtered.map((u) => this.key(u.txid, u.vout)));
43
+ for (const [k, entry] of this.change) {
44
+ if (!existing.has(k) &&
45
+ !this.spent.has(k) &&
46
+ entry.utxo.scriptPubkey.equals(scriptPubkey)) {
47
+ filtered.push(entry.utxo);
48
+ }
49
+ }
50
+ return filtered;
51
+ }
52
+ purge() {
53
+ const now = Date.now();
54
+ for (const [k, exp] of this.spent) {
55
+ if (exp <= now)
56
+ this.spent.delete(k);
57
+ }
58
+ for (const [k, entry] of this.change) {
59
+ if (entry.expiresAt <= now)
60
+ this.change.delete(k);
61
+ }
62
+ }
63
+ }
64
+ const _pending = new PendingTracker();
65
+ class Wallet {
66
+ privateKey;
67
+ pubkey;
68
+ _address;
69
+ _scriptPubkey;
70
+ _utxoSet;
71
+ rpc;
72
+ network;
73
+ _uncommitted = null;
74
+ constructor(privateKey, network = params_1.MAINNET, rpc) {
75
+ this.privateKey = privateKey;
76
+ this.network = network;
77
+ this.rpc = rpc ?? null;
78
+ this.pubkey = (0, keys_1.privkeyToPubkey)(privateKey, true);
79
+ this._address = (0, keys_1.pubkeyToP2wpkhAddress)(this.pubkey, network);
80
+ const keyhash = (0, keys_1.hash160)(this.pubkey);
81
+ this._scriptPubkey = (0, script_1.p2wpkhScriptPubkey)(keyhash);
82
+ this._utxoSet = new utxo_1.UtxoSet();
83
+ }
84
+ get address() {
85
+ return this._address;
86
+ }
87
+ get publicKey() {
88
+ return this.pubkey;
89
+ }
90
+ get scriptPubkey() {
91
+ return this._scriptPubkey;
92
+ }
93
+ get utxoSet() {
94
+ return this._utxoSet;
95
+ }
96
+ /** The network this wallet operates on */
97
+ getNetwork() {
98
+ return this.network;
99
+ }
100
+ /** Returns the primary address (Phase 1: single address, no HD) */
101
+ freshAddress() {
102
+ return this._address;
103
+ }
104
+ /** Sync UTXOs from RPC, filtered by pending spend tracker. */
105
+ async syncUtxos() {
106
+ if (!this.rpc) {
107
+ throw new Error('No RPC client configured for UTXO sync');
108
+ }
109
+ const unspent = await this.rpc.listUnspent(0, 9999999, [this._address]);
110
+ this._utxoSet.clear();
111
+ const fetched = [];
112
+ for (const u of unspent) {
113
+ const amountDgb = u['amount'];
114
+ const amountSat = BigInt(Math.round(amountDgb * 1e8));
115
+ fetched.push({
116
+ txid: u['txid'],
117
+ vout: u['vout'],
118
+ amountSat,
119
+ scriptPubkey: this._scriptPubkey,
120
+ confirmations: u['confirmations'] ?? 0,
121
+ });
122
+ }
123
+ // Apply pending tracker: remove spent, inject change
124
+ const resolved = _pending.apply(fetched, this._scriptPubkey);
125
+ for (const u of resolved) {
126
+ this._utxoSet.add(u);
127
+ }
128
+ }
129
+ /** Manually add a UTXO */
130
+ addUtxo(utxo) {
131
+ this._utxoSet.add(utxo);
132
+ }
133
+ /** Mark a UTXO as spent */
134
+ spendUtxo(txid, vout) {
135
+ this._utxoSet.remove(txid, vout);
136
+ }
137
+ /** Get balance in DGB string */
138
+ async balance() {
139
+ if (this.rpc) {
140
+ await this.syncUtxos();
141
+ }
142
+ return this._utxoSet.totalDgb;
143
+ }
144
+ /**
145
+ * Build a signed payment transaction.
146
+ *
147
+ * Marks UTXOs as spent locally but defers module-level tracking to
148
+ * broadcast() so a failed RPC call can roll back cleanly.
149
+ */
150
+ async buildPayment(params) {
151
+ const { toAddress, amountSat, feeSat = 50000n, opReturnData } = params;
152
+ // Sync UTXOs from RPC before selecting (matches Python SDK behavior)
153
+ if (this.rpc) {
154
+ await this.syncUtxos();
155
+ }
156
+ // Select UTXOs
157
+ const totalNeeded = amountSat + feeSat;
158
+ const selected = this._utxoSet.select(totalNeeded);
159
+ // Build inputs
160
+ const inputs = selected.map((utxo) => ({
161
+ txid: utxo.txid,
162
+ vout: utxo.vout,
163
+ amountSat: utxo.amountSat,
164
+ scriptPubkey: utxo.scriptPubkey,
165
+ sequence: 0xffffffff,
166
+ }));
167
+ // Build transaction
168
+ const tx = (0, transaction_1.buildPaymentTx)({
169
+ inputs,
170
+ toAddress,
171
+ amountSat,
172
+ changeAddress: this._address,
173
+ feeSat,
174
+ opReturnData,
175
+ network: this.network,
176
+ });
177
+ // Sign all inputs
178
+ for (let i = 0; i < tx.inputs.length; i++) {
179
+ tx.signInput(i, this.privateKey);
180
+ }
181
+ // Compute txid (possible after signing)
182
+ const computedTxid = tx.txid();
183
+ // Find change output
184
+ let changeUtxo;
185
+ for (let i = 0; i < tx.outputs.length; i++) {
186
+ const out = tx.outputs[i];
187
+ if (out.scriptPubkey.equals(this._scriptPubkey) && out.amountSat > 0n) {
188
+ changeUtxo = {
189
+ txid: computedTxid,
190
+ vout: i,
191
+ amountSat: out.amountSat,
192
+ scriptPubkey: this._scriptPubkey,
193
+ confirmations: 0,
194
+ };
195
+ break;
196
+ }
197
+ }
198
+ // Stash uncommitted state for broadcast rollback
199
+ this._uncommitted = {
200
+ spentOutpoints: selected.map((u) => ({ txid: u.txid, vout: u.vout })),
201
+ changeUtxo,
202
+ selected: [...selected],
203
+ };
204
+ // Update local UTXO tracking: remove spent, add change
205
+ for (const utxo of selected) {
206
+ this._utxoSet.remove(utxo.txid, utxo.vout);
207
+ }
208
+ if (changeUtxo) {
209
+ this._utxoSet.add(changeUtxo);
210
+ }
211
+ return tx;
212
+ }
213
+ /**
214
+ * Broadcast a signed transaction. Returns txid.
215
+ *
216
+ * On success, commits spend info to the module-level pending tracker
217
+ * so other Wallet instances (same process) see the spent outpoints.
218
+ * On failure, rolls back local UTXO state so the wallet can retry.
219
+ */
220
+ async broadcast(tx) {
221
+ if (!this.rpc) {
222
+ throw new Error('No RPC client configured for broadcast');
223
+ }
224
+ try {
225
+ const txid = await this.rpc.sendRawTransaction(tx.hex());
226
+ // Broadcast succeeded — commit to module-level tracker
227
+ if (this._uncommitted) {
228
+ _pending.recordSpend(this._uncommitted.spentOutpoints, this._uncommitted.changeUtxo);
229
+ this._uncommitted = null;
230
+ }
231
+ return txid;
232
+ }
233
+ catch (err) {
234
+ // Broadcast failed — roll back local state
235
+ if (this._uncommitted) {
236
+ for (const utxo of this._uncommitted.selected) {
237
+ this._utxoSet.add(utxo);
238
+ }
239
+ if (this._uncommitted.changeUtxo) {
240
+ this._utxoSet.remove(this._uncommitted.changeUtxo.txid, this._uncommitted.changeUtxo.vout);
241
+ }
242
+ this._uncommitted = null;
243
+ }
244
+ throw err;
245
+ }
246
+ }
247
+ }
248
+ exports.Wallet = Wallet;
249
+ //# sourceMappingURL=wallet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wallet.js","sourceRoot":"","sources":["../../src/wallet/wallet.ts"],"names":[],"mappings":"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"}