@stellar/typescript-wallet-sdk 1.2.0 → 1.3.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/.eslintrc.js +76 -0
- package/.github/workflows/integrationTest.yml +19 -0
- package/.github/workflows/runTests.yml +14 -0
- package/.husky/pre-commit +1 -0
- package/README.md +19 -12
- package/examples/sep24/.env.example +4 -0
- package/examples/sep24/README.md +17 -0
- package/examples/sep24/sep24.ts +69 -14
- package/examples/tsconfig.json +10 -0
- package/jest.config.js +1 -0
- package/jest.integration.config.js +9 -0
- package/lib/bundle.js +6929 -2377
- package/lib/bundle.js.map +1 -1
- package/lib/bundle_browser.js +6915 -2410
- package/lib/bundle_browser.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/walletSdk/Anchor/Sep24.d.ts +65 -22
- package/lib/walletSdk/Anchor/Sep38.d.ts +56 -0
- package/lib/walletSdk/Anchor/Sep6.d.ts +127 -0
- package/lib/walletSdk/Anchor/index.d.ts +91 -1
- package/lib/walletSdk/Asset/index.d.ts +11 -1
- package/lib/walletSdk/Auth/WalletSigner.d.ts +41 -1
- package/lib/walletSdk/Auth/index.d.ts +21 -0
- package/lib/walletSdk/Customer/index.d.ts +70 -0
- package/lib/walletSdk/Exceptions/index.d.ts +45 -2
- package/lib/walletSdk/Horizon/AccountService.d.ts +30 -20
- package/lib/walletSdk/Horizon/Stellar.d.ts +79 -2
- package/lib/walletSdk/Horizon/Transaction/CommonTransactionBuilder.d.ts +57 -0
- package/lib/walletSdk/Horizon/Transaction/SponsoringBuilder.d.ts +38 -0
- package/lib/walletSdk/Horizon/Transaction/TransactionBuilder.d.ts +112 -11
- package/lib/walletSdk/Horizon/index.d.ts +3 -1
- package/lib/walletSdk/Recovery/AccountRecover.d.ts +58 -0
- package/lib/walletSdk/Recovery/index.d.ts +69 -7
- package/lib/walletSdk/Types/anchor.d.ts +17 -2
- package/lib/walletSdk/Types/auth.d.ts +14 -1
- package/lib/walletSdk/Types/horizon.d.ts +17 -6
- package/lib/walletSdk/Types/index.d.ts +15 -3
- package/lib/walletSdk/Types/recovery.d.ts +128 -0
- package/lib/walletSdk/Types/sep12.d.ts +57 -0
- package/lib/walletSdk/Types/sep38.d.ts +93 -0
- package/lib/walletSdk/Types/sep6.d.ts +160 -0
- package/lib/walletSdk/Types/watcher.d.ts +7 -2
- package/lib/walletSdk/Utils/extractAxiosErrorData.d.ts +2 -0
- package/lib/walletSdk/Utils/index.d.ts +1 -0
- package/lib/walletSdk/Utils/toml.d.ts +2 -2
- package/lib/walletSdk/Watcher/getTransactions.d.ts +8 -0
- package/lib/walletSdk/Watcher/index.d.ts +41 -4
- package/lib/walletSdk/index.d.ts +43 -5
- package/package.json +17 -4
- package/src/index.ts +2 -0
- package/src/walletSdk/Anchor/Sep24.ts +93 -86
- package/src/walletSdk/Anchor/Sep38.ts +180 -0
- package/src/walletSdk/Anchor/Sep6.ts +291 -0
- package/src/walletSdk/Anchor/index.ts +138 -5
- package/src/walletSdk/Asset/index.ts +21 -4
- package/src/walletSdk/Auth/WalletSigner.ts +23 -5
- package/src/walletSdk/Auth/index.ts +24 -5
- package/src/walletSdk/Customer/index.ts +174 -0
- package/src/walletSdk/Exceptions/index.ts +115 -4
- package/src/walletSdk/Horizon/AccountService.ts +33 -21
- package/src/walletSdk/Horizon/Stellar.ts +89 -5
- package/src/walletSdk/Horizon/Transaction/CommonTransactionBuilder.ts +43 -4
- package/src/walletSdk/Horizon/Transaction/SponsoringBuilder.ts +30 -7
- package/src/walletSdk/Horizon/Transaction/TransactionBuilder.ts +88 -15
- package/src/walletSdk/Horizon/index.ts +2 -1
- package/src/walletSdk/Recovery/AccountRecover.ts +255 -0
- package/src/walletSdk/Recovery/index.ts +314 -13
- package/src/walletSdk/Types/anchor.ts +23 -2
- package/src/walletSdk/Types/auth.ts +36 -2
- package/src/walletSdk/Types/horizon.ts +7 -5
- package/src/walletSdk/Types/index.ts +17 -4
- package/src/walletSdk/Types/recovery.ts +152 -0
- package/src/walletSdk/Types/sep12.ts +61 -0
- package/src/walletSdk/Types/sep38.ts +106 -0
- package/src/walletSdk/Types/sep6.ts +168 -0
- package/src/walletSdk/Types/watcher.ts +8 -2
- package/src/walletSdk/Utils/camelToSnakeCase.ts +1 -0
- package/src/walletSdk/Utils/extractAxiosErrorData.ts +28 -0
- package/src/walletSdk/Utils/index.ts +1 -0
- package/src/walletSdk/Utils/toml.ts +2 -2
- package/src/walletSdk/Watcher/getTransactions.ts +65 -0
- package/src/walletSdk/Watcher/index.ts +70 -9
- package/src/walletSdk/index.ts +45 -8
- package/test/README.md +18 -0
- package/test/accountService.test.ts +21 -3
- package/test/customer.test.ts +82 -0
- package/test/docker/docker-compose.yml +97 -0
- package/test/integration.test.ts +166 -0
- package/test/recovery.test.ts +107 -0
- package/test/sep38.test.ts +71 -0
- package/test/sep6.test.ts +240 -0
- package/test/stellar.test.ts +57 -12
- package/test/transaction.test.ts +8 -10
- package/test/tsconfig.json +10 -0
- package/test/utils/index.ts +12 -0
- package/test/wallet.test.ts +60 -21
|
@@ -1,21 +1,30 @@
|
|
|
1
|
-
import StellarSdk, {
|
|
2
|
-
TransactionBuilder as StellarTransactionBuilder,
|
|
3
|
-
Transaction,
|
|
4
|
-
xdr,
|
|
5
|
-
} from "stellar-sdk";
|
|
6
|
-
import { IssuedAssetId } from "../../Asset";
|
|
1
|
+
import StellarSdk, { xdr } from "stellar-sdk";
|
|
7
2
|
|
|
8
3
|
import { CommonTransactionBuilder } from "./CommonTransactionBuilder";
|
|
9
4
|
import { AccountKeypair } from "../Account";
|
|
10
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Used for building transactions that will include a sponsor.
|
|
8
|
+
* Do not create this object directly, use the TransactionBuilder class to create.
|
|
9
|
+
* @class
|
|
10
|
+
*/
|
|
11
11
|
export class SponsoringBuilder extends CommonTransactionBuilder<SponsoringBuilder> {
|
|
12
12
|
private sponsorAccount: AccountKeypair;
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Creates a new instance of the SponsoringBuilder class.
|
|
16
|
+
* @constructor
|
|
17
|
+
* @param {string} sponsoredAddress - The address of the account being sponsored.
|
|
18
|
+
* @param {AccountKeypair} sponsorAccount - The sponsor account keypair.
|
|
19
|
+
* @param {xdr.Operation[]} operations - An array of Stellar operations.
|
|
20
|
+
* @param {(builder: SponsoringBuilder) => SponsoringBuilder} buildingFunction - Function for creating the
|
|
21
|
+
* operations that will be sponsored.
|
|
22
|
+
*/
|
|
14
23
|
constructor(
|
|
15
24
|
sponsoredAddress: string,
|
|
16
25
|
sponsorAccount: AccountKeypair,
|
|
17
26
|
operations: Array<xdr.Operation>,
|
|
18
|
-
buildingFunction: (SponsoringBuilder) => SponsoringBuilder,
|
|
27
|
+
buildingFunction: (builder: SponsoringBuilder) => SponsoringBuilder,
|
|
19
28
|
) {
|
|
20
29
|
super(sponsoredAddress, operations);
|
|
21
30
|
this.sponsorAccount = sponsorAccount;
|
|
@@ -25,6 +34,12 @@ export class SponsoringBuilder extends CommonTransactionBuilder<SponsoringBuilde
|
|
|
25
34
|
this.stopSponsoring();
|
|
26
35
|
}
|
|
27
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Creates a Stellar account with sponsored reserves.
|
|
39
|
+
* @param {AccountKeypair} newAccount - The new account's keypair.
|
|
40
|
+
* @param {number} [startingBalance=0] - The starting balance for the new account (default is 0 XLM).
|
|
41
|
+
* @returns {SponsoringBuilder} The SponsoringBuilder instance.
|
|
42
|
+
*/
|
|
28
43
|
createAccount(
|
|
29
44
|
newAccount: AccountKeypair,
|
|
30
45
|
startingBalance: number = 0,
|
|
@@ -39,6 +54,10 @@ export class SponsoringBuilder extends CommonTransactionBuilder<SponsoringBuilde
|
|
|
39
54
|
return this;
|
|
40
55
|
}
|
|
41
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Start sponsoring the future reserves of an account.
|
|
59
|
+
* @returns {void}
|
|
60
|
+
*/
|
|
42
61
|
startSponsoring() {
|
|
43
62
|
this.operations.push(
|
|
44
63
|
StellarSdk.Operation.beginSponsoringFutureReserves({
|
|
@@ -48,6 +67,10 @@ export class SponsoringBuilder extends CommonTransactionBuilder<SponsoringBuilde
|
|
|
48
67
|
);
|
|
49
68
|
}
|
|
50
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Stop sponsoring the future reserves of an account.
|
|
72
|
+
* @returns {void}
|
|
73
|
+
*/
|
|
51
74
|
stopSponsoring() {
|
|
52
75
|
this.operations.push(
|
|
53
76
|
StellarSdk.Operation.endSponsoringFutureReserves({
|
|
@@ -2,10 +2,9 @@ import StellarSdk, {
|
|
|
2
2
|
TransactionBuilder as StellarTransactionBuilder,
|
|
3
3
|
Account as StellarAccount,
|
|
4
4
|
Transaction,
|
|
5
|
-
|
|
5
|
+
Horizon,
|
|
6
6
|
Memo,
|
|
7
7
|
xdr,
|
|
8
|
-
Networks,
|
|
9
8
|
} from "stellar-sdk";
|
|
10
9
|
|
|
11
10
|
import { Config } from "walletSdk";
|
|
@@ -16,7 +15,7 @@ import {
|
|
|
16
15
|
WithdrawalTxNotPendingUserTransferStartError,
|
|
17
16
|
WithdrawalTxMemoError,
|
|
18
17
|
} from "../../Exceptions";
|
|
19
|
-
import {
|
|
18
|
+
import { StellarAssetId } from "../../Asset";
|
|
20
19
|
import {
|
|
21
20
|
WithdrawTransaction,
|
|
22
21
|
TransactionStatus,
|
|
@@ -26,16 +25,30 @@ import { PathPayOnlyOneAmountError } from "../../Exceptions";
|
|
|
26
25
|
import { CommonTransactionBuilder } from "./CommonTransactionBuilder";
|
|
27
26
|
import { SponsoringBuilder } from "./SponsoringBuilder";
|
|
28
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Used for building transactions.
|
|
30
|
+
* Do not create this object directly, use the Stellar class to create a transaction.
|
|
31
|
+
* @class
|
|
32
|
+
*/
|
|
29
33
|
export class TransactionBuilder extends CommonTransactionBuilder<TransactionBuilder> {
|
|
30
34
|
private cfg: Config;
|
|
31
35
|
private builder: StellarTransactionBuilder;
|
|
32
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Creates a new instance of the TransactionBuilder class for constructing Stellar transactions.
|
|
39
|
+
* @constructor
|
|
40
|
+
* @param {Config} cfg - Configuration object for Stellar operations.
|
|
41
|
+
* @param {StellarAccount} sourceAccount - The source account for the transaction.
|
|
42
|
+
* @param {number} [baseFee] - The base fee for the transaction. If not given will use the config base fee.
|
|
43
|
+
* @param {Memo} [memo] - The memo for the transaction.
|
|
44
|
+
* @param {Horizon.Server.Timebounds} [timebounds] - The timebounds for the transaction. If not given will use the config timebounds.
|
|
45
|
+
*/
|
|
33
46
|
constructor(
|
|
34
47
|
cfg: Config,
|
|
35
48
|
sourceAccount: StellarAccount,
|
|
36
49
|
baseFee?: number,
|
|
37
50
|
memo?: Memo,
|
|
38
|
-
timebounds?: Server.Timebounds,
|
|
51
|
+
timebounds?: Horizon.Server.Timebounds,
|
|
39
52
|
) {
|
|
40
53
|
super(sourceAccount.accountId(), []);
|
|
41
54
|
this.builder = new StellarTransactionBuilder(sourceAccount, {
|
|
@@ -49,9 +62,18 @@ export class TransactionBuilder extends CommonTransactionBuilder<TransactionBuil
|
|
|
49
62
|
}
|
|
50
63
|
}
|
|
51
64
|
|
|
65
|
+
/**
|
|
66
|
+
* Sponsoring a transaction.
|
|
67
|
+
* @param {AccountKeypair} sponsorAccount - The account doing the sponsoring.
|
|
68
|
+
* @param {(builder: SponsoringBuilder) => SponsoringBuilder} buildingFunction - Function for creating the
|
|
69
|
+
* operations that will be sponsored.
|
|
70
|
+
* @see {@link ./SponsoringBuilder.ts} or {@link ./CommonTransactionBuilder.ts} for operations that can be sponsored.
|
|
71
|
+
* @param {AccountKeypair} [sponsoredAccount] - The account that will be sponsored.
|
|
72
|
+
* @returns {TransactionBuilder} The transaction builder to build the transaction before submitting.
|
|
73
|
+
*/
|
|
52
74
|
sponsoring(
|
|
53
75
|
sponsorAccount: AccountKeypair,
|
|
54
|
-
buildingFunction: (SponsoringBuilder) => SponsoringBuilder,
|
|
76
|
+
buildingFunction: (builder: SponsoringBuilder) => SponsoringBuilder,
|
|
55
77
|
sponsoredAccount?: AccountKeypair,
|
|
56
78
|
): TransactionBuilder {
|
|
57
79
|
new SponsoringBuilder(
|
|
@@ -63,6 +85,13 @@ export class TransactionBuilder extends CommonTransactionBuilder<TransactionBuil
|
|
|
63
85
|
return this;
|
|
64
86
|
}
|
|
65
87
|
|
|
88
|
+
/**
|
|
89
|
+
* Creates a Stellar account.
|
|
90
|
+
* @param {AccountKeypair} newAccount - The new account's keypair.
|
|
91
|
+
* @param {number} [startingBalance=1] - The starting balance for the new account (default is 1 XLM).
|
|
92
|
+
* @throws {InsufficientStartingBalanceError} If the starting balance is less than 1.
|
|
93
|
+
* @returns {TransactionBuilder} The TransactionBuilder instance.
|
|
94
|
+
*/
|
|
66
95
|
createAccount(
|
|
67
96
|
newAccount: AccountKeypair,
|
|
68
97
|
startingBalance: number = 1,
|
|
@@ -81,6 +110,13 @@ export class TransactionBuilder extends CommonTransactionBuilder<TransactionBuil
|
|
|
81
110
|
return this;
|
|
82
111
|
}
|
|
83
112
|
|
|
113
|
+
/**
|
|
114
|
+
* Adds a payment operation to transfer an amount of an asset to a destination address.
|
|
115
|
+
* @param {string} destinationAddress - The destination account's public key.
|
|
116
|
+
* @param {StellarAssetId} assetId - The asset to transfer.
|
|
117
|
+
* @param {string} amount - The amount to transfer.
|
|
118
|
+
* @returns {TransactionBuilder} The TransactionBuilder instance.
|
|
119
|
+
*/
|
|
84
120
|
transfer(
|
|
85
121
|
destinationAddress: string,
|
|
86
122
|
assetId: StellarAssetId,
|
|
@@ -98,19 +134,19 @@ export class TransactionBuilder extends CommonTransactionBuilder<TransactionBuil
|
|
|
98
134
|
|
|
99
135
|
/**
|
|
100
136
|
* Creates and adds a path payment operation to the transaction builder.
|
|
101
|
-
*
|
|
102
|
-
* @param {string} destinationAddress - The destination Stellar address to which the payment is sent.
|
|
103
|
-
* @param {StellarAssetId} sendAsset - The asset to be sent.
|
|
104
|
-
* @param {StellarAssetId} destAsset - The asset the destination will receive.
|
|
105
|
-
* @param {string} [sendAmount] - The amount to be sent. Must specify either sendAmount or destAmount,
|
|
137
|
+
* @param {PathPayParams} params - The path payment parameters.
|
|
138
|
+
* @param {string} params.destinationAddress - The destination Stellar address to which the payment is sent.
|
|
139
|
+
* @param {StellarAssetId} params.sendAsset - The asset to be sent.
|
|
140
|
+
* @param {StellarAssetId} params.destAsset - The asset the destination will receive.
|
|
141
|
+
* @param {string} [params.sendAmount] - The amount to be sent. Must specify either sendAmount or destAmount,
|
|
106
142
|
* but not both.
|
|
107
|
-
* @param {string} [destAmount] - The amount to be received by the destination. Must specify either sendAmount or destAmount,
|
|
143
|
+
* @param {string} [params.destAmount] - The amount to be received by the destination. Must specify either sendAmount or destAmount,
|
|
108
144
|
* but not both.
|
|
109
|
-
* @param {string} [destMin] - The minimum amount of the destination asset to be receive. This is a
|
|
145
|
+
* @param {string} [params.destMin] - The minimum amount of the destination asset to be receive. This is a
|
|
110
146
|
* protective measure, it allows you to specify a lower bound for an acceptable conversion. Only used
|
|
111
147
|
* if using sendAmount.
|
|
112
148
|
* (optional, default is ".0000001").
|
|
113
|
-
* @param {string} [sendMax] - The maximum amount of the destination asset to be sent. This is a
|
|
149
|
+
* @param {string} [params.sendMax] - The maximum amount of the destination asset to be sent. This is a
|
|
114
150
|
* protective measure, it allows you to specify an upper bound for an acceptable conversion. Only used
|
|
115
151
|
* if using destAmount.
|
|
116
152
|
* (optional, default is int64 max).
|
|
@@ -157,12 +193,10 @@ export class TransactionBuilder extends CommonTransactionBuilder<TransactionBuil
|
|
|
157
193
|
/**
|
|
158
194
|
* Swap assets using the Stellar network. This swaps using the
|
|
159
195
|
* pathPaymentStrictReceive operation.
|
|
160
|
-
*
|
|
161
196
|
* @param {StellarAssetId} fromAsset - The source asset to be sent.
|
|
162
197
|
* @param {StellarAssetId} toAsset - The destination asset to receive.
|
|
163
198
|
* @param {string} amount - The amount of the source asset to be sent.
|
|
164
199
|
* @param {string} [destMin] - (Optional) The minimum amount of the destination asset to be received.
|
|
165
|
-
*
|
|
166
200
|
* @returns {TransactionBuilder} Returns the current instance of the TransactionBuilder for method chaining.
|
|
167
201
|
*/
|
|
168
202
|
swap(
|
|
@@ -181,16 +215,35 @@ export class TransactionBuilder extends CommonTransactionBuilder<TransactionBuil
|
|
|
181
215
|
return this;
|
|
182
216
|
}
|
|
183
217
|
|
|
218
|
+
/**
|
|
219
|
+
* Adds an operation to the transaction.
|
|
220
|
+
* @param {xdr.Operation} op - The operation to add.
|
|
221
|
+
* @returns {TransactionBuilder} The TransactionBuilder instance.
|
|
222
|
+
*/
|
|
184
223
|
addOperation(op: xdr.Operation): TransactionBuilder {
|
|
185
224
|
this.builder.addOperation(op);
|
|
186
225
|
return this;
|
|
187
226
|
}
|
|
188
227
|
|
|
228
|
+
/**
|
|
229
|
+
* Add a memo for the transaction.
|
|
230
|
+
* @param {Memo} memo - The memo to add to the transaction.
|
|
231
|
+
* @returns {TransactionBuilder} The TransactionBuilder instance.
|
|
232
|
+
*/
|
|
189
233
|
setMemo(memo: Memo): TransactionBuilder {
|
|
190
234
|
this.builder.addMemo(memo);
|
|
191
235
|
return this;
|
|
192
236
|
}
|
|
193
237
|
|
|
238
|
+
/**
|
|
239
|
+
* Add a transfer operation to the builder from a sep-24 withdrawal transaction.
|
|
240
|
+
* @param {WithdrawTransaction} transaction - The withdrawal transaction.
|
|
241
|
+
* @param {StellarAssetId} assetId - The asset ID to transfer.
|
|
242
|
+
* @throws {WithdrawalTxNotPendingUserTransferStartError} If the withdrawal transaction status is not pending_user_transfer_start.
|
|
243
|
+
* @throws {WithdrawalTxMissingMemoError} If the withdrawal transaction is missing a memo.
|
|
244
|
+
* @throws {WithdrawalTxMemoError} If there is an issue with the withdrawal transaction memo.
|
|
245
|
+
* @returns {TransactionBuilder} The TransactionBuilder instance.
|
|
246
|
+
*/
|
|
194
247
|
transferWithdrawalTransaction(
|
|
195
248
|
transaction: WithdrawTransaction,
|
|
196
249
|
assetId: StellarAssetId,
|
|
@@ -226,6 +279,26 @@ export class TransactionBuilder extends CommonTransactionBuilder<TransactionBuil
|
|
|
226
279
|
);
|
|
227
280
|
}
|
|
228
281
|
|
|
282
|
+
/**
|
|
283
|
+
* Merges account into a destination account.
|
|
284
|
+
* **Warning**: This operation will give full control of the account to the destination account,
|
|
285
|
+
* effectively removing the merged account from the network.
|
|
286
|
+
* @param {string} destination - The stellar account merging into.
|
|
287
|
+
* @param {string} [source] - Account that is being merged. If not given then will default to
|
|
288
|
+
* the TransactionBuilder source account.
|
|
289
|
+
* @returns {TransactionBuilder} The TransactionBuilder instance.
|
|
290
|
+
*/
|
|
291
|
+
accountMerge(destination: string, source?: string): TransactionBuilder {
|
|
292
|
+
this.operations.push(
|
|
293
|
+
StellarSdk.Operation.accountMerge({ destination, source }),
|
|
294
|
+
);
|
|
295
|
+
return this;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Builds the Stellar transaction so can be submitted.
|
|
300
|
+
* @returns {Transaction} The built Stellar transaction.
|
|
301
|
+
*/
|
|
229
302
|
build(): Transaction {
|
|
230
303
|
this.operations.forEach((op) => {
|
|
231
304
|
this.builder.addOperation(op);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export { PublicKeypair, SigningKeypair } from "./Account";
|
|
1
|
+
export { AccountKeypair, PublicKeypair, SigningKeypair } from "./Account";
|
|
2
2
|
export { AccountService } from "./AccountService";
|
|
3
3
|
export { Stellar } from "./Stellar";
|
|
4
|
+
export { CommonTransactionBuilder } from "./Transaction/CommonTransactionBuilder";
|
|
4
5
|
export { TransactionBuilder } from "./Transaction/TransactionBuilder";
|
|
5
6
|
export { SponsoringBuilder } from "./Transaction/SponsoringBuilder";
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { AxiosInstance } from "axios";
|
|
2
|
+
import { Horizon, Transaction } from "stellar-sdk";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
RecoveryServer,
|
|
6
|
+
RecoveryServerKey,
|
|
7
|
+
RecoveryServerMap,
|
|
8
|
+
RecoveryServerSigning,
|
|
9
|
+
RecoveryServerSigningMap,
|
|
10
|
+
} from "walletSdk/Types";
|
|
11
|
+
import {
|
|
12
|
+
LostSignerKeyNotFound,
|
|
13
|
+
NoDeviceKeyForAccountError,
|
|
14
|
+
NotAllSignaturesFetchedError,
|
|
15
|
+
RecoveryServerNotFoundError,
|
|
16
|
+
ServerRequestFailedError,
|
|
17
|
+
UnableToDeduceKeyError,
|
|
18
|
+
} from "../Exceptions";
|
|
19
|
+
import {
|
|
20
|
+
AccountKeypair,
|
|
21
|
+
PublicKeypair,
|
|
22
|
+
SponsoringBuilder,
|
|
23
|
+
Stellar,
|
|
24
|
+
} from "../Horizon";
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Used for Account Recovery using Sep-30.
|
|
28
|
+
* @see {@link https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0030.md}
|
|
29
|
+
* @class
|
|
30
|
+
*/
|
|
31
|
+
export abstract class AccountRecover {
|
|
32
|
+
protected stellar: Stellar;
|
|
33
|
+
protected httpClient: AxiosInstance;
|
|
34
|
+
protected servers: RecoveryServerMap;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Creates a new instance of the AccountRecover class.
|
|
38
|
+
* @constructor
|
|
39
|
+
* @param {Stellar} stellar - The stellar instance used to interact with Horizon server.
|
|
40
|
+
* @param {AxiosInstance} httpClient - The client used to make http calls.
|
|
41
|
+
* @param {RecoveryServerMap} servers - The recovery servers to use.
|
|
42
|
+
*/
|
|
43
|
+
constructor(
|
|
44
|
+
stellar: Stellar,
|
|
45
|
+
httpClient: AxiosInstance,
|
|
46
|
+
servers: RecoveryServerMap,
|
|
47
|
+
) {
|
|
48
|
+
this.stellar = stellar;
|
|
49
|
+
this.httpClient = httpClient;
|
|
50
|
+
this.servers = servers;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Sign transaction with recovery servers. It is used to recover an account using
|
|
55
|
+
* [SEP-30](https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0030.md).
|
|
56
|
+
* @param {Transaction} transaction - The transaction with new signer to be signed by recovery servers.
|
|
57
|
+
* @param {AccountKeypair} account - The keypair of the account that will be recovered.
|
|
58
|
+
* @param {RecoveryServerSigningMap} serverAuth - The map of recovery servers to use.
|
|
59
|
+
* @returns {Transaction} - The transaction with recovery server signatures
|
|
60
|
+
* @throws {NotAllSignaturesFetchedError} when all recovery servers don't return signatures
|
|
61
|
+
*/
|
|
62
|
+
async signWithRecoveryServers(
|
|
63
|
+
transaction: Transaction,
|
|
64
|
+
account: AccountKeypair,
|
|
65
|
+
serverAuth: RecoveryServerSigningMap,
|
|
66
|
+
): Promise<Transaction> {
|
|
67
|
+
await Promise.all(
|
|
68
|
+
Object.keys(serverAuth).map((serverKey: RecoveryServerKey) =>
|
|
69
|
+
this.addRecoveryServerTxnSignature(transaction, account.publicKey, [
|
|
70
|
+
serverKey,
|
|
71
|
+
serverAuth[serverKey],
|
|
72
|
+
]),
|
|
73
|
+
),
|
|
74
|
+
);
|
|
75
|
+
return transaction;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Replace a lost device key with a new key.
|
|
80
|
+
* @param {AccountKeypair} account - The target account.
|
|
81
|
+
* @param {AccountKeypair} newKey - The key to replace the lost key with.
|
|
82
|
+
* @param {RecoveryServerSigningMap} serverAuth - A map of recovery servers to use.
|
|
83
|
+
* @param {AccountKeypair} [lostKey] - The lost device key. If not specified, try to deduce the key from the account signers list.
|
|
84
|
+
* @param {AccountKeypair} [sponsorAddress] - The sponsor address of the transaction. Please note that not all SEP-30 servers support signing sponsored transactions.
|
|
85
|
+
* @returns {Promise<Transaction>} The transaction with operations for replacing the device key.
|
|
86
|
+
*/
|
|
87
|
+
async replaceDeviceKey(
|
|
88
|
+
account: AccountKeypair,
|
|
89
|
+
newKey: AccountKeypair,
|
|
90
|
+
serverAuth: RecoveryServerSigningMap,
|
|
91
|
+
lostKey?: AccountKeypair,
|
|
92
|
+
sponsorAddress?: AccountKeypair,
|
|
93
|
+
): Promise<Transaction> {
|
|
94
|
+
const stellarAccount = await this.stellar
|
|
95
|
+
.account()
|
|
96
|
+
.getInfo({ accountAddress: account.publicKey });
|
|
97
|
+
|
|
98
|
+
let lost: AccountKeypair;
|
|
99
|
+
let weight: number;
|
|
100
|
+
|
|
101
|
+
if (lostKey) {
|
|
102
|
+
lost = lostKey;
|
|
103
|
+
|
|
104
|
+
const lostSigner = stellarAccount.signers.find(
|
|
105
|
+
({ key }) => key === lost.publicKey,
|
|
106
|
+
);
|
|
107
|
+
if (!lostSigner) {
|
|
108
|
+
throw new LostSignerKeyNotFound();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
weight = lostSigner.weight;
|
|
112
|
+
} else {
|
|
113
|
+
const deduced = this.deduceKey(stellarAccount, serverAuth);
|
|
114
|
+
lost = PublicKeypair.fromPublicKey(deduced.key);
|
|
115
|
+
weight = deduced.weight;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
let transaction: Transaction;
|
|
119
|
+
|
|
120
|
+
const txBuilder = await this.stellar.transaction({
|
|
121
|
+
sourceAddress: account,
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
if (sponsorAddress) {
|
|
125
|
+
const buildingFunction = (builder: SponsoringBuilder) =>
|
|
126
|
+
builder.removeAccountSigner(lost).addAccountSigner(newKey, weight);
|
|
127
|
+
|
|
128
|
+
transaction = txBuilder
|
|
129
|
+
.sponsoring(sponsorAddress, buildingFunction)
|
|
130
|
+
.build();
|
|
131
|
+
} else {
|
|
132
|
+
transaction = txBuilder
|
|
133
|
+
.removeAccountSigner(lost)
|
|
134
|
+
.addAccountSigner(newKey, weight)
|
|
135
|
+
.build();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return this.signWithRecoveryServers(transaction, account, serverAuth);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
protected getServer = (serverKey: RecoveryServerKey): RecoveryServer => {
|
|
142
|
+
const server = this.servers[serverKey];
|
|
143
|
+
|
|
144
|
+
if (!server) {
|
|
145
|
+
throw new RecoveryServerNotFoundError(serverKey);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return server;
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Try to deduce the lost key. If any of these criteria match, one of the signers
|
|
153
|
+
* from the account will be recognized as the lost device key:
|
|
154
|
+
* 1. Only signer that's not in [serverAuth]
|
|
155
|
+
* 2. All signers in [serverAuth] have the same weight, and the potential signer is
|
|
156
|
+
* the only one with a different weight.
|
|
157
|
+
* @private
|
|
158
|
+
* @param {Horizon.ServerApi.AccountRecord} stellarAccount - The Stellar account to lookup existing signers on account.
|
|
159
|
+
* @param {RecoveryServerSigningMap} serverAuth - A map of recovery servers to use.
|
|
160
|
+
* @returns {Horizon.ServerApi.AccountRecordSigners} The deduced account signer.
|
|
161
|
+
* @throws {NoDeviceKeyForAccountError} When no existing ("lost") device key is found.
|
|
162
|
+
* @throws {UnableToDeduceKeyError} When no criteria match.
|
|
163
|
+
*/
|
|
164
|
+
private deduceKey(
|
|
165
|
+
stellarAccount: Horizon.ServerApi.AccountRecord,
|
|
166
|
+
serverAuth: RecoveryServerSigningMap,
|
|
167
|
+
): Horizon.ServerApi.AccountRecordSigners {
|
|
168
|
+
// Recovery servers addresses
|
|
169
|
+
const recoveryAddresses = Object.values(serverAuth).map(
|
|
170
|
+
({ signerAddress }) => signerAddress,
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
// All signers on stellar account
|
|
174
|
+
const accountSigners = stellarAccount.signers;
|
|
175
|
+
|
|
176
|
+
// All signers on stellar account that are not recovery server
|
|
177
|
+
const nonRecoverySigners = accountSigners.filter(
|
|
178
|
+
({ key, weight }) => !recoveryAddresses.includes(key) && weight > 0,
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
// Throws in case there is no signer other than the recovery signers
|
|
182
|
+
if (nonRecoverySigners.length === 0) {
|
|
183
|
+
throw new NoDeviceKeyForAccountError();
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// If we have only 1 signer that's not a recovery signer deduce it
|
|
187
|
+
// as the lost key
|
|
188
|
+
if (nonRecoverySigners.length === 1) {
|
|
189
|
+
return nonRecoverySigners[0];
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// If we have multiple signers that are not recovery signers:
|
|
193
|
+
|
|
194
|
+
// First get all signers on stellar account that are recovery server
|
|
195
|
+
const recoverySigners = accountSigners.filter(({ key }) =>
|
|
196
|
+
recoveryAddresses.includes(key),
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
// Check if all recovery signers have the same weight
|
|
200
|
+
const recoveryWeight = recoverySigners[0]?.weight || 0;
|
|
201
|
+
if (recoverySigners.find(({ weight }) => weight !== recoveryWeight)) {
|
|
202
|
+
throw new UnableToDeduceKeyError();
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Then in case we have only one non-recovery signer that has different
|
|
206
|
+
// weight deduce it as the lost key
|
|
207
|
+
const filtered = nonRecoverySigners.filter(
|
|
208
|
+
({ weight }) => weight !== recoveryWeight,
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
if (filtered.length !== 1) {
|
|
212
|
+
throw new UnableToDeduceKeyError();
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return filtered[0];
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
private async addRecoveryServerTxnSignature(
|
|
219
|
+
transaction: Transaction,
|
|
220
|
+
accountAddress: string,
|
|
221
|
+
recoveryAuth: [RecoveryServerKey, RecoveryServerSigning],
|
|
222
|
+
): Promise<void> {
|
|
223
|
+
const [serverKey, auth] = recoveryAuth;
|
|
224
|
+
|
|
225
|
+
const server = this.getServer(serverKey);
|
|
226
|
+
|
|
227
|
+
const requestUrl = `${server.endpoint}/accounts/${accountAddress}/sign/${auth.signerAddress}`;
|
|
228
|
+
|
|
229
|
+
let signature: string;
|
|
230
|
+
try {
|
|
231
|
+
const resp = await this.httpClient.post(
|
|
232
|
+
requestUrl,
|
|
233
|
+
{
|
|
234
|
+
transaction: transaction.toXDR(),
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
headers: {
|
|
238
|
+
"Content-Type": "application/json",
|
|
239
|
+
Authorization: `Bearer ${auth.authToken.token}`,
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
signature = resp.data.signature;
|
|
245
|
+
|
|
246
|
+
if (!signature) {
|
|
247
|
+
throw new NotAllSignaturesFetchedError();
|
|
248
|
+
}
|
|
249
|
+
} catch (e) {
|
|
250
|
+
throw new ServerRequestFailedError(e);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
transaction.addSignature(auth.signerAddress, signature);
|
|
254
|
+
}
|
|
255
|
+
}
|