@stellar/typescript-wallet-sdk 1.1.2 → 1.2.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.
@@ -54,3 +54,6 @@ export declare class WithdrawalTxNotPendingUserTransferStartError extends Error
54
54
  export declare class WithdrawalTxMissingMemoError extends Error {
55
55
  constructor();
56
56
  }
57
+ export declare class WithdrawalTxMemoError extends Error {
58
+ constructor();
59
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stellar/typescript-wallet-sdk",
3
- "version": "1.1.2",
3
+ "version": "1.2.0",
4
4
  "engines": {
5
5
  "node": ">=18"
6
6
  },
@@ -29,6 +29,7 @@
29
29
  "stream-browserify": "^3.0.0",
30
30
  "ts-jest": "^29.0.5",
31
31
  "ts-loader": "^9.4.2",
32
+ "ts-node": "^10.9.1",
32
33
  "tslib": "^2.5.0",
33
34
  "typescript": "^5.0.4",
34
35
  "webpack": "^5.83.1",
@@ -40,17 +41,18 @@
40
41
  "jws": "^4.0.0",
41
42
  "lodash": "^4.17.21",
42
43
  "query-string": "^7.1.3",
43
- "stellar-sdk": "^10.4.1",
44
+ "stellar-sdk": "^11.0.0-beta.3",
44
45
  "stream-http": "^3.2.0",
45
46
  "url": "^0.11.0",
46
47
  "util": "^0.12.5",
47
48
  "utility-types": "^3.10.0"
48
49
  },
49
50
  "scripts": {
50
- "prepare": "yarn build",
51
+ "prepare": "husky install",
51
52
  "test": "jest --watchAll",
52
53
  "build:web": "webpack --config webpack.config.js",
53
54
  "build:node": "webpack --env NODE=true --config webpack.config.js",
54
- "build": "run-p build:web build:node"
55
+ "build": "run-p build:web build:node",
56
+ "example:sep24": "ts-node examples/sep24/sep24.ts"
55
57
  }
56
58
  }
package/src/index.ts CHANGED
@@ -23,6 +23,7 @@ export {
23
23
  AccountService,
24
24
  Stellar,
25
25
  TransactionBuilder,
26
+ SponsoringBuilder,
26
27
  } from "./walletSdk/Horizon";
27
28
  export { Recovery } from "./walletSdk/Recovery";
28
29
  export { Watcher } from "./walletSdk/Watcher";
@@ -43,7 +43,9 @@ export class Sep24 {
43
43
 
44
44
  async deposit({
45
45
  assetCode,
46
+
46
47
  authToken,
48
+
47
49
  lang,
48
50
  extraFields,
49
51
  destinationMemo,
@@ -1,8 +1,17 @@
1
- import { Transaction } from "stellar-sdk";
1
+ import {
2
+ Transaction,
3
+ TransactionBuilder as StellarTransactionBuilder,
4
+ FeeBumpTransaction,
5
+ } from "stellar-sdk";
6
+ import { AxiosInstance } from "axios";
7
+
2
8
  import {
3
9
  SignWithClientAccountParams,
4
10
  SignWithDomainAccountParams,
11
+ HttpHeaders,
5
12
  } from "../Types";
13
+ import { AccountKeypair } from "../Horizon/Account";
14
+ import { DefaultClient } from "../";
6
15
 
7
16
  export interface WalletSigner {
8
17
  signWithClientAccount({
@@ -28,3 +37,57 @@ export const DefaultSigner: WalletSigner = {
28
37
  );
29
38
  },
30
39
  };
40
+
41
+ /**
42
+ * Represents a Domain Signer used for signing Stellar transactions with a domain server.
43
+ *
44
+ * @class
45
+ * @implements {WalletSigner}
46
+ */
47
+ export class DomainSigner implements WalletSigner {
48
+ private url: string;
49
+ private client: AxiosInstance;
50
+ private headers: HttpHeaders;
51
+
52
+ /**
53
+ * Create a new instance of the DomainSigner class.
54
+ *
55
+ * @constructor
56
+ * @param {string} url - The URL of the domain server.
57
+ * @param {HttpHeaders} headers - The HTTP headers for requests to the domain server.
58
+ * These headers can be used for authentication purposes.
59
+ */
60
+ constructor(url: string, headers: HttpHeaders) {
61
+ this.url = url;
62
+ this.client = DefaultClient;
63
+ this.headers = headers;
64
+ }
65
+
66
+ signWithClientAccount({
67
+ transaction,
68
+ accountKp,
69
+ }: SignWithClientAccountParams): Transaction {
70
+ transaction.sign(accountKp.keypair);
71
+ return transaction;
72
+ }
73
+
74
+ async signWithDomainAccount({
75
+ transactionXDR,
76
+ networkPassphrase,
77
+ accountKp,
78
+ }: SignWithDomainAccountParams): Promise<Transaction> {
79
+ const response = await this.client.post(
80
+ this.url,
81
+ {
82
+ transactionXDR,
83
+ networkPassphrase,
84
+ },
85
+ { headers: this.headers },
86
+ );
87
+
88
+ return StellarTransactionBuilder.fromXDR(
89
+ response.data.transaction,
90
+ networkPassphrase,
91
+ ) as Transaction;
92
+ }
93
+ }
@@ -55,7 +55,7 @@ export class Sep10 {
55
55
  const challengeResponse = await this.challenge({
56
56
  accountKp,
57
57
  memoId,
58
- clientDomain,
58
+ clientDomain: clientDomain || this.cfg.app.defaultClientDomain,
59
59
  });
60
60
  const signedTransaction = await this.sign({
61
61
  accountKp,
@@ -146,3 +146,16 @@ export class WithdrawalTxMissingMemoError extends Error {
146
146
  Object.setPrototypeOf(this, WithdrawalTxMissingMemoError.prototype);
147
147
  }
148
148
  }
149
+
150
+ export class PathPayOnlyOneAmountError extends Error {
151
+ constructor() {
152
+ super("Must give sendAmount or destAmount value, but not both");
153
+ Object.setPrototypeOf(this, PathPayOnlyOneAmountError.prototype);
154
+ }
155
+ }
156
+ export class WithdrawalTxMemoError extends Error {
157
+ constructor() {
158
+ super(`Error parsing withdrawal transaction memo`);
159
+ Object.setPrototypeOf(this, WithdrawalTxMemoError.prototype);
160
+ }
161
+ }
@@ -0,0 +1,75 @@
1
+ import StellarSdk, { xdr } from "stellar-sdk";
2
+ import { IssuedAssetId } from "../../Asset";
3
+ import { AccountKeypair } from "../Account";
4
+
5
+ export abstract class CommonTransactionBuilder<T> {
6
+ protected sourceAddress: string;
7
+ protected operations: Array<xdr.Operation>;
8
+
9
+ constructor(sourceAddress: string, operations: Array<xdr.Operation>) {
10
+ this.sourceAddress = sourceAddress;
11
+ this.operations = operations;
12
+ }
13
+
14
+ addAssetSupport(asset: IssuedAssetId, trustLimit?: string): T {
15
+ this.operations.push(
16
+ StellarSdk.Operation.changeTrust({
17
+ asset: asset.toAsset(),
18
+ limit: trustLimit,
19
+ source: this.sourceAddress,
20
+ }),
21
+ );
22
+ return this as any as T;
23
+ }
24
+
25
+ removeAssetSupport(asset: IssuedAssetId): T {
26
+ return this.addAssetSupport(asset, "0");
27
+ }
28
+
29
+ addAccountSigner(signerAddress: AccountKeypair, signerWeight: number): T {
30
+ this.operations.push(
31
+ StellarSdk.Operation.setOptions({
32
+ source: this.sourceAddress,
33
+ signer: {
34
+ ed25519PublicKey: signerAddress.publicKey,
35
+ weight: signerWeight,
36
+ },
37
+ }),
38
+ );
39
+ return this as any as T;
40
+ }
41
+
42
+ removeAccountSigner(signerAddress: AccountKeypair): T {
43
+ return this.addAccountSigner(signerAddress, 0);
44
+ }
45
+
46
+ lockAccountMasterKey(): T {
47
+ this.operations.push(
48
+ StellarSdk.Operation.setOptions({
49
+ source: this.sourceAddress,
50
+ masterWeight: 0,
51
+ }),
52
+ );
53
+ return this as any as T;
54
+ }
55
+
56
+ setThreshold({
57
+ low,
58
+ medium,
59
+ high,
60
+ }: {
61
+ low?: number;
62
+ medium?: number;
63
+ high?: number;
64
+ }): T {
65
+ this.operations.push(
66
+ StellarSdk.Operation.setOptions({
67
+ source: this.sourceAddress,
68
+ lowThreshold: low,
69
+ medThreshold: medium,
70
+ highThreshold: high,
71
+ }),
72
+ );
73
+ return this as any as T;
74
+ }
75
+ }
@@ -0,0 +1,58 @@
1
+ import StellarSdk, {
2
+ TransactionBuilder as StellarTransactionBuilder,
3
+ Transaction,
4
+ xdr,
5
+ } from "stellar-sdk";
6
+ import { IssuedAssetId } from "../../Asset";
7
+
8
+ import { CommonTransactionBuilder } from "./CommonTransactionBuilder";
9
+ import { AccountKeypair } from "../Account";
10
+
11
+ export class SponsoringBuilder extends CommonTransactionBuilder<SponsoringBuilder> {
12
+ private sponsorAccount: AccountKeypair;
13
+
14
+ constructor(
15
+ sponsoredAddress: string,
16
+ sponsorAccount: AccountKeypair,
17
+ operations: Array<xdr.Operation>,
18
+ buildingFunction: (SponsoringBuilder) => SponsoringBuilder,
19
+ ) {
20
+ super(sponsoredAddress, operations);
21
+ this.sponsorAccount = sponsorAccount;
22
+
23
+ this.startSponsoring();
24
+ buildingFunction(this);
25
+ this.stopSponsoring();
26
+ }
27
+
28
+ createAccount(
29
+ newAccount: AccountKeypair,
30
+ startingBalance: number = 0,
31
+ ): SponsoringBuilder {
32
+ this.operations.push(
33
+ StellarSdk.Operation.createAccount({
34
+ destination: newAccount.publicKey,
35
+ startingBalance: startingBalance.toString(),
36
+ source: this.sponsorAccount.publicKey,
37
+ }),
38
+ );
39
+ return this;
40
+ }
41
+
42
+ startSponsoring() {
43
+ this.operations.push(
44
+ StellarSdk.Operation.beginSponsoringFutureReserves({
45
+ sponsoredId: this.sourceAddress,
46
+ source: this.sponsorAccount.publicKey,
47
+ }),
48
+ );
49
+ }
50
+
51
+ stopSponsoring() {
52
+ this.operations.push(
53
+ StellarSdk.Operation.endSponsoringFutureReserves({
54
+ source: this.sourceAddress,
55
+ }),
56
+ );
57
+ }
58
+ }
@@ -14,17 +14,22 @@ import {
14
14
  InsufficientStartingBalanceError,
15
15
  WithdrawalTxMissingMemoError,
16
16
  WithdrawalTxNotPendingUserTransferStartError,
17
+ WithdrawalTxMemoError,
17
18
  } from "../../Exceptions";
18
19
  import { IssuedAssetId, StellarAssetId } from "../../Asset";
19
- import { WithdrawTransaction, TransactionStatus } from "../../Types";
20
-
21
- export class TransactionBuilder {
22
- private network: Networks;
23
- private operations: Array<xdr.Operation>;
20
+ import {
21
+ WithdrawTransaction,
22
+ TransactionStatus,
23
+ PathPayParams,
24
+ } from "../../Types";
25
+ import { PathPayOnlyOneAmountError } from "../../Exceptions";
26
+ import { CommonTransactionBuilder } from "./CommonTransactionBuilder";
27
+ import { SponsoringBuilder } from "./SponsoringBuilder";
28
+
29
+ export class TransactionBuilder extends CommonTransactionBuilder<TransactionBuilder> {
30
+ private cfg: Config;
24
31
  private builder: StellarTransactionBuilder;
25
32
 
26
- sourceAccount: string;
27
-
28
33
  constructor(
29
34
  cfg: Config,
30
35
  sourceAccount: StellarAccount,
@@ -32,8 +37,7 @@ export class TransactionBuilder {
32
37
  memo?: Memo,
33
38
  timebounds?: Server.Timebounds,
34
39
  ) {
35
- this.network = cfg.stellar.network;
36
- this.operations = [];
40
+ super(sourceAccount.accountId(), []);
37
41
  this.builder = new StellarTransactionBuilder(sourceAccount, {
38
42
  fee: baseFee ? baseFee.toString() : cfg.stellar.baseFee.toString(),
39
43
  timebounds,
@@ -43,8 +47,20 @@ export class TransactionBuilder {
43
47
  if (!timebounds) {
44
48
  this.builder.setTimeout(cfg.stellar.defaultTimeout);
45
49
  }
50
+ }
46
51
 
47
- this.sourceAccount = sourceAccount.accountId();
52
+ sponsoring(
53
+ sponsorAccount: AccountKeypair,
54
+ buildingFunction: (SponsoringBuilder) => SponsoringBuilder,
55
+ sponsoredAccount?: AccountKeypair,
56
+ ): TransactionBuilder {
57
+ new SponsoringBuilder(
58
+ sponsoredAccount ? sponsoredAccount.publicKey : this.sourceAddress,
59
+ sponsorAccount,
60
+ this.operations,
61
+ buildingFunction,
62
+ );
63
+ return this;
48
64
  }
49
65
 
50
66
  createAccount(
@@ -59,7 +75,7 @@ export class TransactionBuilder {
59
75
  StellarSdk.Operation.createAccount({
60
76
  destination: newAccount.publicKey,
61
77
  startingBalance: startingBalance.toString(),
62
- source: this.sourceAccount,
78
+ source: this.sourceAddress,
63
79
  }),
64
80
  );
65
81
  return this;
@@ -80,39 +96,99 @@ export class TransactionBuilder {
80
96
  return this;
81
97
  }
82
98
 
83
- addOperation(op: xdr.Operation): TransactionBuilder {
84
- this.builder.addOperation(op);
85
- return this;
86
- }
99
+ /**
100
+ * 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,
106
+ * but not both.
107
+ * @param {string} [destAmount] - The amount to be received by the destination. Must specify either sendAmount or destAmount,
108
+ * but not both.
109
+ * @param {string} [destMin] - The minimum amount of the destination asset to be receive. This is a
110
+ * protective measure, it allows you to specify a lower bound for an acceptable conversion. Only used
111
+ * if using sendAmount.
112
+ * (optional, default is ".0000001").
113
+ * @param {string} [sendMax] - The maximum amount of the destination asset to be sent. This is a
114
+ * protective measure, it allows you to specify an upper bound for an acceptable conversion. Only used
115
+ * if using destAmount.
116
+ * (optional, default is int64 max).
117
+ *
118
+ * @returns {TransactionBuilder} - Returns the current TransactionBuilder instance for method chaining.
119
+ */
120
+ pathPay({
121
+ destinationAddress,
122
+ sendAsset,
123
+ destAsset,
124
+ sendAmount,
125
+ destAmount,
126
+ destMin,
127
+ sendMax,
128
+ }: PathPayParams): TransactionBuilder {
129
+ if ((sendAmount && destAmount) || (!sendAmount && !destAmount)) {
130
+ throw new PathPayOnlyOneAmountError();
131
+ }
132
+ if (sendAmount) {
133
+ this.operations.push(
134
+ StellarSdk.Operation.pathPaymentStrictSend({
135
+ destination: destinationAddress,
136
+ sendAsset: sendAsset.toAsset(),
137
+ sendAmount,
138
+ destAsset: destAsset.toAsset(),
139
+ destMin: destMin || ".0000001",
140
+ }),
141
+ );
142
+ } else {
143
+ this.operations.push(
144
+ StellarSdk.Operation.pathPaymentStrictReceive({
145
+ destination: destinationAddress,
146
+ sendAsset: sendAsset.toAsset(),
147
+ destAmount,
148
+ destAsset: destAsset.toAsset(),
149
+ sendMax: sendMax || "922337203685.4775807",
150
+ }),
151
+ );
152
+ }
87
153
 
88
- setMemo(memo: Memo): TransactionBuilder {
89
- this.builder.addMemo(memo);
90
154
  return this;
91
155
  }
92
156
 
93
- addAssetSupport(
94
- asset: IssuedAssetId,
95
- trustLimit?: string,
157
+ /**
158
+ * Swap assets using the Stellar network. This swaps using the
159
+ * pathPaymentStrictReceive operation.
160
+ *
161
+ * @param {StellarAssetId} fromAsset - The source asset to be sent.
162
+ * @param {StellarAssetId} toAsset - The destination asset to receive.
163
+ * @param {string} amount - The amount of the source asset to be sent.
164
+ * @param {string} [destMin] - (Optional) The minimum amount of the destination asset to be received.
165
+ *
166
+ * @returns {TransactionBuilder} Returns the current instance of the TransactionBuilder for method chaining.
167
+ */
168
+ swap(
169
+ fromAsset: StellarAssetId,
170
+ toAsset: StellarAssetId,
171
+ amount: string,
172
+ destMin?: string,
96
173
  ): TransactionBuilder {
97
- this.operations.push(
98
- StellarSdk.Operation.changeTrust({
99
- asset: asset.toAsset(),
100
- limit: trustLimit,
101
- source: this.sourceAccount,
102
- }),
103
- );
174
+ this.pathPay({
175
+ destinationAddress: this.sourceAddress,
176
+ sendAsset: fromAsset,
177
+ destAsset: toAsset,
178
+ sendAmount: amount,
179
+ destMin,
180
+ });
104
181
  return this;
105
182
  }
106
183
 
107
- removeAssetSupport(asset: IssuedAssetId): TransactionBuilder {
108
- return this.addAssetSupport(asset, "0");
184
+ addOperation(op: xdr.Operation): TransactionBuilder {
185
+ this.builder.addOperation(op);
186
+ return this;
109
187
  }
110
188
 
111
- build(): Transaction {
112
- this.operations.forEach((op) => {
113
- this.builder.addOperation(op);
114
- });
115
- return this.builder.build();
189
+ setMemo(memo: Memo): TransactionBuilder {
190
+ this.builder.addMemo(memo);
191
+ return this;
116
192
  }
117
193
 
118
194
  transferWithdrawalTransaction(
@@ -129,12 +205,31 @@ export class TransactionBuilder {
129
205
  throw new WithdrawalTxMissingMemoError();
130
206
  }
131
207
 
132
- return this.setMemo(
133
- new Memo(transaction.withdraw_memo_type, transaction.withdraw_memo),
134
- ).transfer(
208
+ if (transaction.withdraw_memo_type === "hash") {
209
+ try {
210
+ const buffer = Buffer.from(transaction.withdraw_memo, "base64");
211
+ const memo = Memo.hash(buffer.toString("hex"));
212
+ this.setMemo(memo);
213
+ } catch {
214
+ throw new WithdrawalTxMemoError();
215
+ }
216
+ } else {
217
+ this.setMemo(
218
+ new Memo(transaction.withdraw_memo_type, transaction.withdraw_memo),
219
+ );
220
+ }
221
+
222
+ return this.transfer(
135
223
  transaction.withdraw_anchor_account,
136
224
  assetId,
137
225
  transaction.amount_in,
138
226
  );
139
227
  }
228
+
229
+ build(): Transaction {
230
+ this.operations.forEach((op) => {
231
+ this.builder.addOperation(op);
232
+ });
233
+ return this.builder.build();
234
+ }
140
235
  }
@@ -2,3 +2,4 @@ export { PublicKeypair, SigningKeypair } from "./Account";
2
2
  export { AccountService } from "./AccountService";
3
3
  export { Stellar } from "./Stellar";
4
4
  export { TransactionBuilder } from "./Transaction/TransactionBuilder";
5
+ export { SponsoringBuilder } from "./Transaction/SponsoringBuilder";
@@ -41,3 +41,7 @@ export type SignWithDomainAccountParams = {
41
41
  networkPassphrase: NetworkPassphrase;
42
42
  accountKp: AccountKeypair;
43
43
  };
44
+
45
+ export type HttpHeaders = {
46
+ [key: string]: string;
47
+ };
@@ -1,6 +1,7 @@
1
1
  import { Memo, Server, xdr, Transaction } from "stellar-sdk";
2
2
  import { AccountKeypair } from "../Horizon/Account";
3
3
  import { TransactionBuilder } from "../Horizon/Transaction/TransactionBuilder";
4
+ import { StellarAssetId } from "../Asset";
4
5
 
5
6
  export enum NETWORK_URLS {
6
7
  PUBLIC = "https://horizon.stellar.org",
@@ -9,7 +10,7 @@ export enum NETWORK_URLS {
9
10
 
10
11
  export type TransactionParams = {
11
12
  sourceAddress: AccountKeypair;
12
- baseFee: number;
13
+ baseFee?: number;
13
14
  memo?: Memo;
14
15
  timebounds?: Server.Timebounds | number;
15
16
  };
@@ -38,3 +39,13 @@ export enum HORIZON_ORDER {
38
39
  ASC = "asc",
39
40
  DESC = "desc",
40
41
  }
42
+
43
+ export type PathPayParams = {
44
+ destinationAddress: string;
45
+ sendAsset: StellarAssetId;
46
+ destAsset: StellarAssetId;
47
+ sendAmount?: string;
48
+ destAmount?: string;
49
+ destMin?: string;
50
+ sendMax?: string;
51
+ };
@@ -131,9 +131,15 @@ export const DefaultClient = axios.create({
131
131
  export class ApplicationConfiguration {
132
132
  defaultSigner: WalletSigner;
133
133
  defaultClient: AxiosInstance;
134
+ defaultClientDomain?: string;
134
135
 
135
- constructor(defaultSigner?: WalletSigner, defaultClient?: AxiosInstance) {
136
+ constructor(
137
+ defaultSigner?: WalletSigner,
138
+ defaultClient?: AxiosInstance,
139
+ defaultClientDomain?: string,
140
+ ) {
136
141
  this.defaultSigner = defaultSigner || DefaultSigner;
137
142
  this.defaultClient = defaultClient || DefaultClient;
143
+ this.defaultClientDomain = defaultClientDomain;
138
144
  }
139
145
  }