@btc-vision/transaction 1.2.2 → 1.2.4
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/browser/_version.d.ts +1 -1
- package/browser/crypto/crypto-browser.d.ts +1 -1
- package/browser/generators/builders/CalldataGenerator.d.ts +1 -1
- package/browser/generators/builders/DeploymentGenerator.d.ts +1 -1
- package/browser/generators/builders/MineableReward.d.ts +7 -0
- package/browser/index.js +1 -1
- package/browser/opnet.d.ts +4 -0
- package/browser/transaction/TransactionFactory.d.ts +19 -4
- package/browser/transaction/browser/WalletConnection.d.ts +18 -0
- package/browser/transaction/browser/types/Xverse.d.ts +24 -10
- package/browser/transaction/builders/ChallengeSolutionTransaction.d.ts +18 -0
- package/browser/transaction/builders/DeploymentTransaction.d.ts +4 -0
- package/browser/transaction/builders/SharedInteractionTransaction.d.ts +5 -0
- package/browser/transaction/builders/TransactionBuilder.d.ts +2 -0
- package/browser/transaction/enums/TransactionType.d.ts +3 -4
- package/browser/transaction/interfaces/ITransactionParameters.d.ts +6 -0
- package/browser/transaction/mineable/ChallengeGenerator.d.ts +9 -0
- package/browser/utxo/interfaces/IUTXO.d.ts +1 -1
- package/browser/verification/TapscriptVerificator.d.ts +1 -1
- package/build/_version.d.ts +1 -1
- package/build/_version.js +1 -1
- package/build/generators/Generator.js +1 -1
- package/build/generators/builders/CalldataGenerator.d.ts +1 -1
- package/build/generators/builders/CalldataGenerator.js +7 -26
- package/build/generators/builders/DeploymentGenerator.d.ts +1 -1
- package/build/generators/builders/DeploymentGenerator.js +9 -6
- package/build/generators/builders/LegacyCalldataGenerator.js +5 -1
- package/build/generators/builders/MineableReward.d.ts +7 -0
- package/build/generators/builders/MineableReward.js +48 -0
- package/build/opnet.d.ts +4 -0
- package/build/opnet.js +4 -0
- package/build/transaction/TransactionFactory.d.ts +19 -4
- package/build/transaction/TransactionFactory.js +32 -0
- package/build/transaction/browser/WalletConnection.d.ts +18 -0
- package/build/transaction/browser/WalletConnection.js +95 -0
- package/build/transaction/browser/extensions/UnisatSigner.js +5 -2
- package/build/transaction/browser/extensions/XverseSigner.js +15 -9
- package/build/transaction/browser/types/Xverse.d.ts +24 -10
- package/build/transaction/builders/ChallengeSolutionTransaction.d.ts +18 -0
- package/build/transaction/builders/ChallengeSolutionTransaction.js +51 -0
- package/build/transaction/builders/DeploymentTransaction.d.ts +4 -0
- package/build/transaction/builders/DeploymentTransaction.js +23 -4
- package/build/transaction/builders/InteractionTransaction.js +1 -1
- package/build/transaction/builders/SharedInteractionTransaction.d.ts +5 -0
- package/build/transaction/builders/SharedInteractionTransaction.js +35 -13
- package/build/transaction/builders/TransactionBuilder.d.ts +2 -0
- package/build/transaction/builders/TransactionBuilder.js +2 -0
- package/build/transaction/enums/TransactionType.d.ts +3 -4
- package/build/transaction/enums/TransactionType.js +3 -4
- package/build/transaction/interfaces/ITransactionParameters.d.ts +6 -0
- package/build/transaction/mineable/ChallengeGenerator.d.ts +9 -0
- package/build/transaction/mineable/ChallengeGenerator.js +28 -0
- package/build/transaction/shared/TweakedTransaction.js +1 -1
- package/build/utxo/interfaces/IUTXO.d.ts +1 -1
- package/build/verification/TapscriptVerificator.d.ts +1 -1
- package/build/verification/TapscriptVerificator.js +2 -8
- package/package.json +3 -3
- package/src/_version.ts +1 -1
- package/src/generators/Generator.ts +1 -1
- package/src/generators/builders/CalldataGenerator.ts +10 -41
- package/src/generators/builders/DeploymentGenerator.ts +18 -7
- package/src/generators/builders/LegacyCalldataGenerator.ts +5 -1
- package/src/generators/builders/MineableReward.ts +66 -0
- package/src/opnet.ts +5 -0
- package/src/transaction/TransactionFactory.ts +66 -3
- package/src/transaction/browser/WalletConnection.ts +110 -0
- package/src/transaction/browser/extensions/UnisatSigner.ts +7 -3
- package/src/transaction/browser/extensions/XverseSigner.ts +24 -23
- package/src/transaction/browser/types/Xverse.ts +50 -36
- package/src/transaction/builders/ChallengeSolutionTransaction.ts +88 -0
- package/src/transaction/builders/DeploymentTransaction.ts +46 -3
- package/src/transaction/builders/InteractionTransaction.ts +1 -0
- package/src/transaction/builders/SharedInteractionTransaction.ts +54 -14
- package/src/transaction/builders/TransactionBuilder.ts +3 -0
- package/src/transaction/enums/TransactionType.ts +3 -4
- package/src/transaction/interfaces/ITransactionParameters.ts +8 -15
- package/src/transaction/mineable/ChallengeGenerator.ts +39 -0
- package/src/transaction/shared/TweakedTransaction.ts +1 -1
- package/src/utxo/interfaces/IUTXO.ts +1 -1
- package/src/verification/TapscriptVerificator.ts +3 -18
|
@@ -4,6 +4,7 @@ import { DeploymentTransaction } from './builders/DeploymentTransaction.js';
|
|
|
4
4
|
import { FundingTransaction } from './builders/FundingTransaction.js';
|
|
5
5
|
import { InteractionTransaction } from './builders/InteractionTransaction.js';
|
|
6
6
|
import { TransactionBuilder } from './builders/TransactionBuilder.js';
|
|
7
|
+
import { ChallengeSolutionTransaction } from './builders/ChallengeSolutionTransaction.js';
|
|
7
8
|
export class TransactionFactory {
|
|
8
9
|
async createCustomScriptTransaction(interactionParameters) {
|
|
9
10
|
if (!interactionParameters.to) {
|
|
@@ -89,6 +90,7 @@ export class TransactionFactory {
|
|
|
89
90
|
...interactionParameters,
|
|
90
91
|
utxos: this.getUTXOAsTransaction(signedTransaction.tx, interactionParameters.to, 0),
|
|
91
92
|
randomBytes: preTransaction.getRndBytes(),
|
|
93
|
+
preimage: preTransaction.getPreimage(),
|
|
92
94
|
nonWitnessUtxo: signedTransaction.tx.toBuffer(),
|
|
93
95
|
estimatedFees: preTransaction.estimatedFees,
|
|
94
96
|
};
|
|
@@ -98,6 +100,7 @@ export class TransactionFactory {
|
|
|
98
100
|
signedTransaction.tx.toHex(),
|
|
99
101
|
outTx.toHex(),
|
|
100
102
|
this.getUTXOAsTransaction(signedTransaction.tx, interactionParameters.from, 1),
|
|
103
|
+
preTransaction.getPreimage().toString('hex'),
|
|
101
104
|
];
|
|
102
105
|
}
|
|
103
106
|
async signDeployment(deploymentParameters) {
|
|
@@ -127,6 +130,7 @@ export class TransactionFactory {
|
|
|
127
130
|
...deploymentParameters,
|
|
128
131
|
utxos: [newUtxo],
|
|
129
132
|
randomBytes: preTransaction.getRndBytes(),
|
|
133
|
+
preimage: preTransaction.getPreimage(),
|
|
130
134
|
nonWitnessUtxo: signedTransaction.toBuffer(),
|
|
131
135
|
optionalOutputs: [],
|
|
132
136
|
};
|
|
@@ -148,6 +152,7 @@ export class TransactionFactory {
|
|
|
148
152
|
contractPubKey: finalTransaction.contractPubKey,
|
|
149
153
|
p2trAddress: finalTransaction.p2trAddress,
|
|
150
154
|
utxos: [refundUTXO],
|
|
155
|
+
preimage: preTransaction.getPreimage().toString('hex'),
|
|
151
156
|
};
|
|
152
157
|
}
|
|
153
158
|
async createBTCTransfer(parameters) {
|
|
@@ -162,6 +167,18 @@ export class TransactionFactory {
|
|
|
162
167
|
nextUTXOs: this.getAllNewUTXOs(resp.original, resp.tx, parameters.from),
|
|
163
168
|
};
|
|
164
169
|
}
|
|
170
|
+
async createChallengeSolution(parameters) {
|
|
171
|
+
if (!parameters.from) {
|
|
172
|
+
throw new Error('Field "from" not provided.');
|
|
173
|
+
}
|
|
174
|
+
const resp = await this._createChallengeSolution(parameters);
|
|
175
|
+
return {
|
|
176
|
+
estimatedFees: resp.estimatedFees,
|
|
177
|
+
original: resp.original,
|
|
178
|
+
tx: resp.tx.toHex(),
|
|
179
|
+
nextUTXOs: this.getAllNewUTXOs(resp.original, resp.tx, parameters.from),
|
|
180
|
+
};
|
|
181
|
+
}
|
|
165
182
|
getAllNewUTXOs(original, tx, to) {
|
|
166
183
|
const outputs = original.getOutputs();
|
|
167
184
|
const utxos = [];
|
|
@@ -178,6 +195,21 @@ export class TransactionFactory {
|
|
|
178
195
|
}
|
|
179
196
|
return utxos;
|
|
180
197
|
}
|
|
198
|
+
async _createChallengeSolution(parameters) {
|
|
199
|
+
if (!parameters.to)
|
|
200
|
+
throw new Error('Field "to" not provided.');
|
|
201
|
+
const challengeTransaction = new ChallengeSolutionTransaction(parameters);
|
|
202
|
+
const signedTransaction = await challengeTransaction.signTransaction();
|
|
203
|
+
if (!signedTransaction) {
|
|
204
|
+
throw new Error('Could not sign funding transaction.');
|
|
205
|
+
}
|
|
206
|
+
return {
|
|
207
|
+
tx: signedTransaction,
|
|
208
|
+
original: challengeTransaction,
|
|
209
|
+
estimatedFees: challengeTransaction.estimatedFees,
|
|
210
|
+
nextUTXOs: this.getUTXOAsTransaction(signedTransaction, parameters.to, 0),
|
|
211
|
+
};
|
|
212
|
+
}
|
|
181
213
|
async createFundTransaction(parameters) {
|
|
182
214
|
if (!parameters.to)
|
|
183
215
|
throw new Error('Field "to" not provided.');
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Address } from '../../opnet.js';
|
|
2
|
+
import { UnisatSigner } from './extensions/UnisatSigner.js';
|
|
3
|
+
import { XverseSigner } from './extensions/XverseSigner.js';
|
|
4
|
+
export declare enum SupportedWallets {
|
|
5
|
+
Unisat = "unisat",
|
|
6
|
+
Xverse = "xverse"
|
|
7
|
+
}
|
|
8
|
+
export declare class WalletConnection {
|
|
9
|
+
wallet_type: SupportedWallets | null;
|
|
10
|
+
private unisatSigner;
|
|
11
|
+
private xverseSigner;
|
|
12
|
+
connect(): Promise<void>;
|
|
13
|
+
disconnect(): Promise<void>;
|
|
14
|
+
switchTo(walletType: SupportedWallets): Promise<void>;
|
|
15
|
+
getAddress(): Address;
|
|
16
|
+
getSigner(): UnisatSigner | XverseSigner;
|
|
17
|
+
}
|
|
18
|
+
export default WalletConnection;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { Address } from '../../opnet.js';
|
|
2
|
+
import { UnisatSigner } from './extensions/UnisatSigner.js';
|
|
3
|
+
import { XverseSigner } from './extensions/XverseSigner.js';
|
|
4
|
+
export var SupportedWallets;
|
|
5
|
+
(function (SupportedWallets) {
|
|
6
|
+
SupportedWallets["Unisat"] = "unisat";
|
|
7
|
+
SupportedWallets["Xverse"] = "xverse";
|
|
8
|
+
})(SupportedWallets || (SupportedWallets = {}));
|
|
9
|
+
export class WalletConnection {
|
|
10
|
+
constructor() {
|
|
11
|
+
this.wallet_type = null;
|
|
12
|
+
this.unisatSigner = null;
|
|
13
|
+
this.xverseSigner = null;
|
|
14
|
+
}
|
|
15
|
+
async connect() {
|
|
16
|
+
if (this.wallet_type) {
|
|
17
|
+
throw new Error('Wallet already connected');
|
|
18
|
+
}
|
|
19
|
+
this.unisatSigner = new UnisatSigner();
|
|
20
|
+
this.xverseSigner = new XverseSigner();
|
|
21
|
+
if (window.opnet || window.unisat) {
|
|
22
|
+
try {
|
|
23
|
+
await this.unisatSigner.init();
|
|
24
|
+
this.wallet_type = SupportedWallets.Unisat;
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
if (error instanceof Error) {
|
|
29
|
+
throw new Error(error.message);
|
|
30
|
+
}
|
|
31
|
+
throw new Error('Error connecting wallet');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (window.BitcoinProvider) {
|
|
35
|
+
try {
|
|
36
|
+
await this.xverseSigner.init();
|
|
37
|
+
this.wallet_type = SupportedWallets.Xverse;
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
if (error instanceof Error) {
|
|
42
|
+
throw new Error(error.message);
|
|
43
|
+
}
|
|
44
|
+
throw new Error('Error connecting wallet');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
throw new Error('Wallet not found');
|
|
48
|
+
}
|
|
49
|
+
async disconnect() {
|
|
50
|
+
if (!this.unisatSigner || !this.xverseSigner) {
|
|
51
|
+
throw new Error('Wallet not connected');
|
|
52
|
+
}
|
|
53
|
+
if (this.wallet_type === SupportedWallets.Unisat) {
|
|
54
|
+
this.unisatSigner.unisat.disconnect();
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
await this.xverseSigner.BitcoinProvider.request('wallet_disconnect', null);
|
|
58
|
+
}
|
|
59
|
+
this.wallet_type = null;
|
|
60
|
+
}
|
|
61
|
+
async switchTo(walletType) {
|
|
62
|
+
if (!this.unisatSigner || !this.xverseSigner) {
|
|
63
|
+
throw new Error('Wallet not connected');
|
|
64
|
+
}
|
|
65
|
+
if (this.wallet_type === walletType)
|
|
66
|
+
return;
|
|
67
|
+
if (walletType === SupportedWallets.Unisat) {
|
|
68
|
+
await this.unisatSigner.init();
|
|
69
|
+
this.wallet_type = SupportedWallets.Unisat;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
await this.xverseSigner.init();
|
|
73
|
+
this.wallet_type = SupportedWallets.Xverse;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
getAddress() {
|
|
77
|
+
if (!this.unisatSigner || !this.xverseSigner) {
|
|
78
|
+
throw new Error('Wallet not connected');
|
|
79
|
+
}
|
|
80
|
+
if (this.wallet_type === SupportedWallets.Unisat) {
|
|
81
|
+
return Address.fromString(this.unisatSigner.getPublicKey().toString('hex'));
|
|
82
|
+
}
|
|
83
|
+
return Address.fromString(this.xverseSigner.getPublicKey().toString('hex'));
|
|
84
|
+
}
|
|
85
|
+
getSigner() {
|
|
86
|
+
if (!this.unisatSigner || !this.xverseSigner) {
|
|
87
|
+
throw new Error('Wallet not connected');
|
|
88
|
+
}
|
|
89
|
+
if (this.wallet_type === SupportedWallets.Unisat) {
|
|
90
|
+
return this.unisatSigner;
|
|
91
|
+
}
|
|
92
|
+
return this.xverseSigner;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
export default WalletConnection;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { crypto as bitCrypto,
|
|
1
|
+
import { crypto as bitCrypto, script as bitScript, networks, Psbt, toXOnly, } from '@btc-vision/bitcoin';
|
|
2
2
|
import { EcKeyPair } from '../../../keypair/EcKeyPair.js';
|
|
3
|
+
import { canSignNonTaprootInput, isTaprootInput } from '../../../signer/SignerUtils.js';
|
|
3
4
|
import { CustomKeypair } from '../BrowserSignerBase.js';
|
|
4
5
|
import { UnisatNetwork } from '../types/Unisat.js';
|
|
5
|
-
import { canSignNonTaprootInput, isTaprootInput } from '../../../signer/SignerUtils.js';
|
|
6
6
|
export class UnisatSigner extends CustomKeypair {
|
|
7
7
|
constructor() {
|
|
8
8
|
super();
|
|
@@ -67,6 +67,9 @@ export class UnisatSigner extends CustomKeypair {
|
|
|
67
67
|
throw new Error(`Invalid network: ${network}`);
|
|
68
68
|
}
|
|
69
69
|
const publicKey = await this.unisat.getPublicKey();
|
|
70
|
+
if (publicKey === '') {
|
|
71
|
+
throw new Error('Unlock your wallet first');
|
|
72
|
+
}
|
|
70
73
|
this._publicKey = Buffer.from(publicKey, 'hex');
|
|
71
74
|
this._p2wpkh = EcKeyPair.getP2WPKHAddress(this, this.network);
|
|
72
75
|
this._p2tr = EcKeyPair.getTaprootAddress(this, this.network);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { networks, Psbt, toXOnly } from '@btc-vision/bitcoin';
|
|
2
2
|
import { EcKeyPair } from '../../../keypair/EcKeyPair.js';
|
|
3
|
-
import { CustomKeypair } from '../BrowserSignerBase.js';
|
|
4
3
|
import { canSignNonTaprootInput, isTaprootInput, pubkeyInScript, } from '../../../signer/SignerUtils.js';
|
|
4
|
+
import { CustomKeypair } from '../BrowserSignerBase.js';
|
|
5
5
|
export class XverseSigner extends CustomKeypair {
|
|
6
6
|
constructor() {
|
|
7
7
|
super();
|
|
@@ -50,7 +50,7 @@ export class XverseSigner extends CustomKeypair {
|
|
|
50
50
|
async init() {
|
|
51
51
|
if (this.isInitialized)
|
|
52
52
|
return;
|
|
53
|
-
const connectResult =
|
|
53
|
+
const connectResult = await this.BitcoinProvider.request('wallet_connect', null);
|
|
54
54
|
if ('error' in connectResult)
|
|
55
55
|
throw new Error(connectResult.error.message);
|
|
56
56
|
const payementAddress = connectResult.result.addresses.find((address) => address.purpose === 'payment');
|
|
@@ -120,7 +120,7 @@ export class XverseSigner extends CustomKeypair {
|
|
|
120
120
|
const toSignPsbts = [];
|
|
121
121
|
const options = [];
|
|
122
122
|
for (const psbt of transactions) {
|
|
123
|
-
const hex = psbt.
|
|
123
|
+
const hex = psbt.toBase64();
|
|
124
124
|
toSignPsbts.push(hex);
|
|
125
125
|
const toSignInputs = psbt.data.inputs
|
|
126
126
|
.map((input, i) => {
|
|
@@ -166,10 +166,13 @@ export class XverseSigner extends CustomKeypair {
|
|
|
166
166
|
toSignInputs: toSignInputs,
|
|
167
167
|
});
|
|
168
168
|
}
|
|
169
|
-
const
|
|
169
|
+
const toSignInputs = {
|
|
170
|
+
[this.p2wpkh]: options[0].toSignInputs?.map((input) => input.index) || [],
|
|
171
|
+
};
|
|
172
|
+
const callSign = await this.BitcoinProvider.request('signPsbt', {
|
|
170
173
|
psbt: toSignPsbts[0],
|
|
171
|
-
signInputs:
|
|
172
|
-
})
|
|
174
|
+
signInputs: toSignInputs,
|
|
175
|
+
});
|
|
173
176
|
if ('error' in callSign)
|
|
174
177
|
throw new Error(callSign.error.message);
|
|
175
178
|
const signedPsbts = Psbt.fromBase64(callSign.result.psbt);
|
|
@@ -234,10 +237,13 @@ export class XverseSigner extends CustomKeypair {
|
|
|
234
237
|
toSignInputs: toSign.flat(),
|
|
235
238
|
};
|
|
236
239
|
const psbt = transaction.toBase64();
|
|
237
|
-
const
|
|
240
|
+
const toSignInputs = {
|
|
241
|
+
[this.p2wpkh]: opts.toSignInputs?.map((input) => input.index) || [],
|
|
242
|
+
};
|
|
243
|
+
const callSign = await this.BitcoinProvider.request('signPsbt', {
|
|
238
244
|
psbt,
|
|
239
|
-
signInputs:
|
|
240
|
-
})
|
|
245
|
+
signInputs: toSignInputs,
|
|
246
|
+
});
|
|
241
247
|
if ('error' in callSign)
|
|
242
248
|
throw new Error(callSign.error.message);
|
|
243
249
|
return Psbt.fromBase64(callSign.result.psbt);
|
|
@@ -3,12 +3,11 @@ export declare enum XverseNetwork {
|
|
|
3
3
|
testnet = "testnet",
|
|
4
4
|
signet = "Signet"
|
|
5
5
|
}
|
|
6
|
-
|
|
6
|
+
type XverseRPCResponse<T = unknown> = {
|
|
7
7
|
id: string;
|
|
8
8
|
jsonrpc: string;
|
|
9
9
|
result: T;
|
|
10
|
-
}
|
|
11
|
-
export type XverseRPCError = {
|
|
10
|
+
} | {
|
|
12
11
|
id: string;
|
|
13
12
|
jsonrpc: string;
|
|
14
13
|
error: {
|
|
@@ -16,17 +15,29 @@ export type XverseRPCError = {
|
|
|
16
15
|
message: string;
|
|
17
16
|
};
|
|
18
17
|
};
|
|
19
|
-
|
|
18
|
+
type XverseRPCGetAccountResponse = XverseRPCResponse<{
|
|
20
19
|
addresses: {
|
|
21
20
|
address: string;
|
|
22
21
|
addressType: string;
|
|
23
22
|
publicKey: string;
|
|
24
|
-
purpose:
|
|
23
|
+
purpose: 'stacks' | 'payment' | 'ordinals';
|
|
25
24
|
}[];
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
walletType: string;
|
|
26
|
+
}>;
|
|
27
|
+
type XverseRPCSignPsbtResponse = XverseRPCResponse<{
|
|
28
|
+
psbt: string;
|
|
29
|
+
}>;
|
|
30
|
+
type XverseRPCGetBalanceResponse = XverseRPCResponse<{
|
|
31
|
+
confirmed: string;
|
|
32
|
+
total: string;
|
|
33
|
+
unconfirmed: string;
|
|
34
|
+
}>;
|
|
35
|
+
export type XVersePSBTInput = {
|
|
28
36
|
psbt: string;
|
|
29
|
-
|
|
37
|
+
signInputs: {
|
|
38
|
+
[x: string]: number[];
|
|
39
|
+
} | undefined;
|
|
40
|
+
};
|
|
30
41
|
interface InscriptionData {
|
|
31
42
|
address: string;
|
|
32
43
|
amount: number;
|
|
@@ -66,11 +77,14 @@ interface SignedTransactionResult {
|
|
|
66
77
|
raw: string;
|
|
67
78
|
}
|
|
68
79
|
export interface Xverse {
|
|
69
|
-
|
|
80
|
+
request(method: string, params: unknown): Promise<XverseRPCResponse>;
|
|
81
|
+
request(method: 'wallet_connect' | 'wallet_getAccount', params: null): Promise<XverseRPCGetAccountResponse>;
|
|
82
|
+
request(method: 'wallet_disconnect', params: null): Promise<XverseRPCResponse<null>>;
|
|
83
|
+
request(method: 'getBalance', params: null): Promise<XverseRPCGetBalanceResponse>;
|
|
84
|
+
request(method: 'signPsbt', params: XVersePSBTInput): Promise<XverseRPCSignPsbtResponse>;
|
|
70
85
|
addListener: (event: string, callback: (...args: unknown[]) => void) => void;
|
|
71
86
|
createInscription: (data: InscriptionData) => Promise<InscriptionResult>;
|
|
72
87
|
createRepeatInscriptions: (data: RepeatInscriptionsData) => Promise<InscriptionResult[]>;
|
|
73
|
-
request: (method: string, params: unknown) => Promise<XverseRPCResponse>;
|
|
74
88
|
sendBtcTransaction: (transaction: BtcTransaction) => Promise<TransactionResult>;
|
|
75
89
|
signMessage: (message: string) => Promise<SignedMessageResult>;
|
|
76
90
|
signMultipleTransactions: (transactions: BtcTransaction[]) => Promise<SignedTransactionResult[]>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { TransactionType } from '../enums/TransactionType.js';
|
|
2
|
+
import { IChallengeSolutionTransactionParameters } from '../interfaces/ITransactionParameters.js';
|
|
3
|
+
import { Psbt, PsbtInput, Signer } from '@btc-vision/bitcoin';
|
|
4
|
+
import { TransactionBuilder } from './TransactionBuilder.js';
|
|
5
|
+
import { ECPairInterface } from 'ecpair';
|
|
6
|
+
export declare class ChallengeSolutionTransaction extends TransactionBuilder<TransactionType.CHALLENGE_SOLUTION> {
|
|
7
|
+
readonly type: TransactionType.CHALLENGE_SOLUTION;
|
|
8
|
+
protected amount: bigint;
|
|
9
|
+
protected readonly challengeSolution: Buffer;
|
|
10
|
+
constructor(parameters: IChallengeSolutionTransactionParameters);
|
|
11
|
+
protected buildTransaction(): Promise<void>;
|
|
12
|
+
protected signInput(transaction: Psbt, input: PsbtInput, i: number, signer: Signer | ECPairInterface, reverse?: boolean, errored?: boolean): Promise<void>;
|
|
13
|
+
protected customFinalizerP2SH: (inputIndex: number, input: PsbtInput, scriptA: Buffer, isSegwit: boolean, isP2SH: boolean, isP2WSH: boolean) => {
|
|
14
|
+
finalScriptSig: Buffer | undefined;
|
|
15
|
+
finalScriptWitness: Buffer | undefined;
|
|
16
|
+
};
|
|
17
|
+
protected getSignerKey(): Signer | ECPairInterface;
|
|
18
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { TransactionType } from '../enums/TransactionType.js';
|
|
2
|
+
import { getFinalScripts, opcodes, script } from '@btc-vision/bitcoin';
|
|
3
|
+
import { TransactionBuilder } from './TransactionBuilder.js';
|
|
4
|
+
export class ChallengeSolutionTransaction extends TransactionBuilder {
|
|
5
|
+
constructor(parameters) {
|
|
6
|
+
super(parameters);
|
|
7
|
+
this.type = TransactionType.CHALLENGE_SOLUTION;
|
|
8
|
+
this.customFinalizerP2SH = (inputIndex, input, scriptA, isSegwit, isP2SH, isP2WSH) => {
|
|
9
|
+
const inputDecoded = this.inputs[inputIndex];
|
|
10
|
+
if (isP2SH && inputDecoded && inputDecoded.redeemScript) {
|
|
11
|
+
const scriptSig = script.compile([this.challengeSolution, inputDecoded.redeemScript]);
|
|
12
|
+
return {
|
|
13
|
+
finalScriptSig: scriptSig,
|
|
14
|
+
finalScriptWitness: undefined,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
return getFinalScripts(inputIndex, input, scriptA, isSegwit, isP2SH, isP2WSH, false);
|
|
18
|
+
};
|
|
19
|
+
this.amount = parameters.amount;
|
|
20
|
+
this.challengeSolution = parameters.challengeSolution;
|
|
21
|
+
this.internalInit();
|
|
22
|
+
}
|
|
23
|
+
async buildTransaction() {
|
|
24
|
+
if (!this.to) {
|
|
25
|
+
throw new Error('Recipient address is required');
|
|
26
|
+
}
|
|
27
|
+
this.addInputsFromUTXO();
|
|
28
|
+
if (this.isPubKeyDestination) {
|
|
29
|
+
const pubKeyScript = script.compile([
|
|
30
|
+
Buffer.from(this.to.replace('0x', ''), 'hex'),
|
|
31
|
+
opcodes.OP_CHECKSIG,
|
|
32
|
+
]);
|
|
33
|
+
this.addOutput({
|
|
34
|
+
value: Number(this.amount),
|
|
35
|
+
script: pubKeyScript,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
this.addOutput({
|
|
40
|
+
value: Number(this.amount),
|
|
41
|
+
address: this.to,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
await this.addRefundOutput(this.amount + this.addOptionalOutputsAndGetAmount());
|
|
45
|
+
}
|
|
46
|
+
async signInput(transaction, input, i, signer, reverse = false, errored = false) {
|
|
47
|
+
}
|
|
48
|
+
getSignerKey() {
|
|
49
|
+
return this.signer;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -4,9 +4,12 @@ import { Payment, Psbt } from '@btc-vision/bitcoin';
|
|
|
4
4
|
import { TransactionBuilder } from './TransactionBuilder.js';
|
|
5
5
|
import { TapLeafScript } from '../interfaces/Tap.js';
|
|
6
6
|
import { Address } from '../../keypair/Address.js';
|
|
7
|
+
import { IMineableReward } from '../mineable/ChallengeGenerator.js';
|
|
7
8
|
export declare class DeploymentTransaction extends TransactionBuilder<TransactionType.DEPLOYMENT> {
|
|
8
9
|
static readonly MAXIMUM_CONTRACT_SIZE: number;
|
|
9
10
|
type: TransactionType.DEPLOYMENT;
|
|
11
|
+
protected readonly preimage: Buffer;
|
|
12
|
+
protected readonly rewardChallenge: IMineableReward;
|
|
10
13
|
protected readonly _contractAddress: Address;
|
|
11
14
|
protected tapLeafScript: TapLeafScript | null;
|
|
12
15
|
private targetScriptRedeem;
|
|
@@ -25,6 +28,7 @@ export declare class DeploymentTransaction extends TransactionBuilder<Transactio
|
|
|
25
28
|
get contractAddress(): Address;
|
|
26
29
|
get p2trAddress(): string;
|
|
27
30
|
getRndBytes(): Buffer;
|
|
31
|
+
getPreimage(): Buffer;
|
|
28
32
|
protected contractSignerXOnlyPubKey(): Buffer;
|
|
29
33
|
protected buildTransaction(): Promise<void>;
|
|
30
34
|
protected signInputsWalletBased(transaction: Psbt): Promise<void>;
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { TransactionType } from '../enums/TransactionType.js';
|
|
2
2
|
import { crypto as bitCrypto, toXOnly, } from '@btc-vision/bitcoin';
|
|
3
|
-
import { TransactionBuilder } from './TransactionBuilder.js';
|
|
3
|
+
import { MINIMUM_AMOUNT_CA, MINIMUM_AMOUNT_REWARD, TransactionBuilder, } from './TransactionBuilder.js';
|
|
4
4
|
import { DeploymentGenerator } from '../../generators/builders/DeploymentGenerator.js';
|
|
5
5
|
import { EcKeyPair } from '../../keypair/EcKeyPair.js';
|
|
6
6
|
import { BitcoinUtils } from '../../utils/BitcoinUtils.js';
|
|
7
7
|
import { Compressor } from '../../bytecode/Compressor.js';
|
|
8
8
|
import { SharedInteractionTransaction } from './SharedInteractionTransaction.js';
|
|
9
9
|
import { Address } from '../../keypair/Address.js';
|
|
10
|
+
import { ChallengeGenerator } from '../mineable/ChallengeGenerator.js';
|
|
10
11
|
const p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fn;
|
|
11
12
|
export class DeploymentTransaction extends TransactionBuilder {
|
|
12
13
|
constructor(parameters) {
|
|
@@ -24,7 +25,6 @@ export class DeploymentTransaction extends TransactionBuilder {
|
|
|
24
25
|
}
|
|
25
26
|
const scriptSolution = [
|
|
26
27
|
this.randomBytes,
|
|
27
|
-
this.internalPubKeyToXOnly(),
|
|
28
28
|
input.tapScriptSig[0].signature,
|
|
29
29
|
input.tapScriptSig[1].signature,
|
|
30
30
|
];
|
|
@@ -42,10 +42,12 @@ export class DeploymentTransaction extends TransactionBuilder {
|
|
|
42
42
|
this.verifyCalldata();
|
|
43
43
|
}
|
|
44
44
|
this.randomBytes = parameters.randomBytes || BitcoinUtils.rndBytes();
|
|
45
|
+
this.preimage = parameters.preimage || BitcoinUtils.getSafeRandomValues(128);
|
|
46
|
+
this.rewardChallenge = ChallengeGenerator.generateMineableReward(this.preimage, this.network);
|
|
45
47
|
this.contractSeed = this.getContractSeed();
|
|
46
48
|
this.contractSigner = EcKeyPair.fromSeedKeyPair(this.contractSeed, this.network);
|
|
47
49
|
this.deploymentGenerator = new DeploymentGenerator(Buffer.from(this.signer.publicKey), this.contractSignerXOnlyPubKey(), this.network);
|
|
48
|
-
this.compiledTargetScript = this.deploymentGenerator.compile(this.bytecode, this.randomBytes, this.calldata);
|
|
50
|
+
this.compiledTargetScript = this.deploymentGenerator.compile(this.bytecode, this.randomBytes, this.preimage, this.calldata);
|
|
49
51
|
this.scriptTree = this.getScriptTree();
|
|
50
52
|
this.internalInit();
|
|
51
53
|
this._contractPubKey = '0x' + this.contractSeed.toString('hex');
|
|
@@ -63,6 +65,9 @@ export class DeploymentTransaction extends TransactionBuilder {
|
|
|
63
65
|
getRndBytes() {
|
|
64
66
|
return this.randomBytes;
|
|
65
67
|
}
|
|
68
|
+
getPreimage() {
|
|
69
|
+
return this.preimage;
|
|
70
|
+
}
|
|
66
71
|
contractSignerXOnlyPubKey() {
|
|
67
72
|
return toXOnly(Buffer.from(this.contractSigner.publicKey));
|
|
68
73
|
}
|
|
@@ -89,10 +94,24 @@ export class DeploymentTransaction extends TransactionBuilder {
|
|
|
89
94
|
};
|
|
90
95
|
this.addInputsFromUTXO();
|
|
91
96
|
const amountSpent = this.getTransactionOPNetFee();
|
|
97
|
+
let amountToCA;
|
|
98
|
+
if (amountSpent > MINIMUM_AMOUNT_REWARD + MINIMUM_AMOUNT_CA) {
|
|
99
|
+
amountToCA = MINIMUM_AMOUNT_CA;
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
amountToCA = amountSpent;
|
|
103
|
+
}
|
|
92
104
|
this.addOutput({
|
|
93
|
-
value: Number(
|
|
105
|
+
value: Number(amountToCA),
|
|
94
106
|
address: this.contractAddress.p2tr(this.network),
|
|
95
107
|
});
|
|
108
|
+
if (amountToCA === MINIMUM_AMOUNT_CA &&
|
|
109
|
+
amountSpent - MINIMUM_AMOUNT_CA > MINIMUM_AMOUNT_REWARD) {
|
|
110
|
+
this.addOutput({
|
|
111
|
+
value: Number(amountSpent - amountToCA),
|
|
112
|
+
address: this.rewardChallenge.address,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
96
115
|
await this.addRefundOutput(amountSpent + this.addOptionalOutputsAndGetAmount());
|
|
97
116
|
}
|
|
98
117
|
async signInputsWalletBased(transaction) {
|
|
@@ -6,7 +6,7 @@ export class InteractionTransaction extends SharedInteractionTransaction {
|
|
|
6
6
|
this.type = TransactionType.INTERACTION;
|
|
7
7
|
this.tapLeafScript = null;
|
|
8
8
|
this.contractSecret = this.generateSecret();
|
|
9
|
-
this.compiledTargetScript = this.calldataGenerator.compile(this.calldata, this.contractSecret);
|
|
9
|
+
this.compiledTargetScript = this.calldataGenerator.compile(this.calldata, this.contractSecret, this.preimage);
|
|
10
10
|
this.scriptTree = this.getScriptTree();
|
|
11
11
|
this.internalInit();
|
|
12
12
|
}
|
|
@@ -4,6 +4,7 @@ import { TransactionBuilder } from './TransactionBuilder.js';
|
|
|
4
4
|
import { TransactionType } from '../enums/TransactionType.js';
|
|
5
5
|
import { CalldataGenerator } from '../../generators/builders/CalldataGenerator.js';
|
|
6
6
|
import { SharedInteractionParameters } from '../interfaces/ITransactionParameters.js';
|
|
7
|
+
import { IMineableReward } from '../mineable/ChallengeGenerator.js';
|
|
7
8
|
export declare abstract class SharedInteractionTransaction<T extends TransactionType> extends TransactionBuilder<T> {
|
|
8
9
|
static readonly MAXIMUM_CALLDATA_SIZE: number;
|
|
9
10
|
readonly randomBytes: Buffer;
|
|
@@ -11,6 +12,8 @@ export declare abstract class SharedInteractionTransaction<T extends Transaction
|
|
|
11
12
|
protected leftOverFundsScriptRedeem: Payment | null;
|
|
12
13
|
protected abstract readonly compiledTargetScript: Buffer;
|
|
13
14
|
protected abstract readonly scriptTree: Taptree;
|
|
15
|
+
protected readonly preimage: Buffer;
|
|
16
|
+
protected readonly rewardChallenge: IMineableReward;
|
|
14
17
|
protected calldataGenerator: CalldataGenerator;
|
|
15
18
|
protected readonly calldata: Buffer;
|
|
16
19
|
protected abstract readonly contractSecret: Buffer;
|
|
@@ -19,6 +22,7 @@ export declare abstract class SharedInteractionTransaction<T extends Transaction
|
|
|
19
22
|
protected constructor(parameters: SharedInteractionParameters);
|
|
20
23
|
getContractSecret(): Buffer;
|
|
21
24
|
getRndBytes(): Buffer;
|
|
25
|
+
getPreimage(): Buffer;
|
|
22
26
|
protected generateSecret(): Buffer;
|
|
23
27
|
protected scriptSignerXOnlyPubKey(): Buffer;
|
|
24
28
|
protected generateKeyPairFromSeed(): ECPairInterface;
|
|
@@ -32,6 +36,7 @@ export declare abstract class SharedInteractionTransaction<T extends Transaction
|
|
|
32
36
|
finalScriptWitness: Buffer<ArrayBufferLike>;
|
|
33
37
|
};
|
|
34
38
|
protected signInputsWalletBased(transaction: Psbt): Promise<void>;
|
|
39
|
+
private createMineableRewardOutputs;
|
|
35
40
|
private signInputsNonWalletBased;
|
|
36
41
|
private getPubKeys;
|
|
37
42
|
private generateRedeemScripts;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { address, toXOnly } from '@btc-vision/bitcoin';
|
|
2
|
-
import { TransactionBuilder } from './TransactionBuilder.js';
|
|
2
|
+
import { MINIMUM_AMOUNT_CA, MINIMUM_AMOUNT_REWARD, TransactionBuilder } from './TransactionBuilder.js';
|
|
3
3
|
import { CalldataGenerator } from '../../generators/builders/CalldataGenerator.js';
|
|
4
4
|
import { Compressor } from '../../bytecode/Compressor.js';
|
|
5
5
|
import { EcKeyPair } from '../../keypair/EcKeyPair.js';
|
|
6
6
|
import { BitcoinUtils } from '../../utils/BitcoinUtils.js';
|
|
7
|
+
import { ChallengeGenerator } from '../mineable/ChallengeGenerator.js';
|
|
7
8
|
export class SharedInteractionTransaction extends TransactionBuilder {
|
|
8
9
|
constructor(parameters) {
|
|
9
10
|
super(parameters);
|
|
@@ -27,7 +28,9 @@ export class SharedInteractionTransaction extends TransactionBuilder {
|
|
|
27
28
|
if (!parameters.calldata) {
|
|
28
29
|
throw new Error('Calldata is required');
|
|
29
30
|
}
|
|
31
|
+
this.preimage = parameters.preimage || BitcoinUtils.getSafeRandomValues(128);
|
|
30
32
|
this.disableAutoRefund = parameters.disableAutoRefund || false;
|
|
33
|
+
this.rewardChallenge = ChallengeGenerator.generateMineableReward(this.preimage, this.network);
|
|
31
34
|
this.calldata = Compressor.compress(parameters.calldata);
|
|
32
35
|
this.randomBytes = parameters.randomBytes || BitcoinUtils.rndBytes();
|
|
33
36
|
this.scriptSigner = this.generateKeyPairFromSeed();
|
|
@@ -39,6 +42,9 @@ export class SharedInteractionTransaction extends TransactionBuilder {
|
|
|
39
42
|
getRndBytes() {
|
|
40
43
|
return this.randomBytes;
|
|
41
44
|
}
|
|
45
|
+
getPreimage() {
|
|
46
|
+
return this.preimage;
|
|
47
|
+
}
|
|
42
48
|
generateSecret() {
|
|
43
49
|
if (!this.to)
|
|
44
50
|
throw new Error('To address is required');
|
|
@@ -51,8 +57,6 @@ export class SharedInteractionTransaction extends TransactionBuilder {
|
|
|
51
57
|
return EcKeyPair.fromSeedKeyPair(this.randomBytes, this.network);
|
|
52
58
|
}
|
|
53
59
|
async buildTransaction() {
|
|
54
|
-
if (!this.to)
|
|
55
|
-
throw new Error('To address is required');
|
|
56
60
|
const selectedRedeem = this.scriptSigner
|
|
57
61
|
? this.targetScriptRedeem
|
|
58
62
|
: this.leftOverFundsScriptRedeem;
|
|
@@ -73,15 +77,7 @@ export class SharedInteractionTransaction extends TransactionBuilder {
|
|
|
73
77
|
if (!this.regenerated) {
|
|
74
78
|
this.addInputsFromUTXO();
|
|
75
79
|
}
|
|
76
|
-
|
|
77
|
-
this.addOutput({
|
|
78
|
-
value: Number(amountSpent),
|
|
79
|
-
address: this.to,
|
|
80
|
-
});
|
|
81
|
-
const amount = this.addOptionalOutputsAndGetAmount();
|
|
82
|
-
if (!this.disableAutoRefund) {
|
|
83
|
-
await this.addRefundOutput(amountSpent + amount);
|
|
84
|
-
}
|
|
80
|
+
await this.createMineableRewardOutputs();
|
|
85
81
|
}
|
|
86
82
|
async signInputs(transaction) {
|
|
87
83
|
if (!this.scriptSigner) {
|
|
@@ -125,7 +121,6 @@ export class SharedInteractionTransaction extends TransactionBuilder {
|
|
|
125
121
|
}
|
|
126
122
|
return [
|
|
127
123
|
this.contractSecret,
|
|
128
|
-
this.internalPubKeyToXOnly(),
|
|
129
124
|
input.tapScriptSig[0].signature,
|
|
130
125
|
input.tapScriptSig[1].signature,
|
|
131
126
|
];
|
|
@@ -159,6 +154,33 @@ export class SharedInteractionTransaction extends TransactionBuilder {
|
|
|
159
154
|
}
|
|
160
155
|
}
|
|
161
156
|
}
|
|
157
|
+
async createMineableRewardOutputs() {
|
|
158
|
+
if (!this.to)
|
|
159
|
+
throw new Error('To address is required');
|
|
160
|
+
const amountSpent = this.getTransactionOPNetFee();
|
|
161
|
+
let amountToCA;
|
|
162
|
+
if (amountSpent > MINIMUM_AMOUNT_REWARD + MINIMUM_AMOUNT_CA) {
|
|
163
|
+
amountToCA = MINIMUM_AMOUNT_CA;
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
amountToCA = amountSpent;
|
|
167
|
+
}
|
|
168
|
+
this.addOutput({
|
|
169
|
+
value: Number(amountToCA),
|
|
170
|
+
address: this.to,
|
|
171
|
+
});
|
|
172
|
+
if (amountToCA === MINIMUM_AMOUNT_CA &&
|
|
173
|
+
amountSpent - MINIMUM_AMOUNT_CA > MINIMUM_AMOUNT_REWARD) {
|
|
174
|
+
this.addOutput({
|
|
175
|
+
value: Number(amountSpent - amountToCA),
|
|
176
|
+
address: this.rewardChallenge.address,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
const amount = this.addOptionalOutputsAndGetAmount();
|
|
180
|
+
if (!this.disableAutoRefund) {
|
|
181
|
+
await this.addRefundOutput(amountSpent + amount);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
162
184
|
async signInputsNonWalletBased(transaction) {
|
|
163
185
|
for (let i = 0; i < transaction.data.inputs.length; i++) {
|
|
164
186
|
if (i === 0) {
|
|
@@ -6,6 +6,8 @@ import { UTXO } from '../../utxo/interfaces/IUTXO.js';
|
|
|
6
6
|
import { ECPairInterface } from 'ecpair';
|
|
7
7
|
import { TweakedTransaction } from '../shared/TweakedTransaction.js';
|
|
8
8
|
import { UnisatSigner } from '../browser/extensions/UnisatSigner.js';
|
|
9
|
+
export declare const MINIMUM_AMOUNT_REWARD: bigint;
|
|
10
|
+
export declare const MINIMUM_AMOUNT_CA: bigint;
|
|
9
11
|
export declare abstract class TransactionBuilder<T extends TransactionType> extends TweakedTransaction {
|
|
10
12
|
static readonly LOCK_LEAF_SCRIPT: Buffer;
|
|
11
13
|
static readonly MINIMUM_DUST: bigint;
|
|
@@ -4,6 +4,8 @@ import { EcKeyPair } from '../../keypair/EcKeyPair.js';
|
|
|
4
4
|
import { AddressVerificator } from '../../keypair/AddressVerificator.js';
|
|
5
5
|
import { TweakedTransaction } from '../shared/TweakedTransaction.js';
|
|
6
6
|
initEccLib(ecc);
|
|
7
|
+
export const MINIMUM_AMOUNT_REWARD = 540n;
|
|
8
|
+
export const MINIMUM_AMOUNT_CA = 330n;
|
|
7
9
|
export class TransactionBuilder extends TweakedTransaction {
|
|
8
10
|
constructor(parameters) {
|
|
9
11
|
super(parameters);
|