@stellar/typescript-wallet-sdk 1.5.0 → 1.6.0-beta.1719867067726

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 (35) hide show
  1. package/CHANGELOG.MD +11 -1
  2. package/lib/bundle.js +7354 -3358
  3. package/lib/bundle.js.map +1 -1
  4. package/lib/bundle_browser.js +1117 -11
  5. package/lib/bundle_browser.js.map +1 -1
  6. package/lib/index.d.ts +1 -0
  7. package/lib/walletSdk/Exceptions/index.d.ts +15 -0
  8. package/lib/walletSdk/Types/anchor.d.ts +5 -1
  9. package/lib/walletSdk/Types/index.d.ts +1 -0
  10. package/lib/walletSdk/Types/sep7.d.ts +15 -0
  11. package/lib/walletSdk/Uri/Sep7Base.d.ts +187 -0
  12. package/lib/walletSdk/Uri/Sep7Pay.d.ts +121 -0
  13. package/lib/walletSdk/Uri/Sep7Tx.d.ts +133 -0
  14. package/lib/walletSdk/Uri/index.d.ts +4 -0
  15. package/lib/walletSdk/Uri/sep7Parser.d.ts +60 -0
  16. package/lib/walletSdk/Utils/index.d.ts +2 -1
  17. package/package.json +3 -3
  18. package/src/index.ts +9 -0
  19. package/src/walletSdk/Auth/WalletSigner.ts +3 -3
  20. package/src/walletSdk/Customer/index.ts +7 -7
  21. package/src/walletSdk/Exceptions/index.ts +38 -1
  22. package/src/walletSdk/Horizon/Account.ts +2 -1
  23. package/src/walletSdk/Types/anchor.ts +4 -0
  24. package/src/walletSdk/Types/index.ts +1 -0
  25. package/src/walletSdk/Types/sep7.ts +19 -0
  26. package/src/walletSdk/Uri/Sep7Base.ts +311 -0
  27. package/src/walletSdk/Uri/Sep7Pay.ts +169 -0
  28. package/src/walletSdk/Uri/Sep7Tx.ts +193 -0
  29. package/src/walletSdk/Uri/index.ts +9 -0
  30. package/src/walletSdk/Uri/sep7Parser.ts +220 -0
  31. package/src/walletSdk/Utils/index.ts +2 -1
  32. package/src/walletSdk/Watcher/index.ts +3 -1
  33. package/test/customer.test.ts +7 -7
  34. package/test/integration/anchorplatform.test.ts +2 -2
  35. package/test/sep7.test.ts +825 -0
@@ -0,0 +1,193 @@
1
+ import { Networks, Transaction } from "@stellar/stellar-sdk";
2
+ import {
3
+ Sep7Base,
4
+ sep7ReplacementsFromString,
5
+ sep7ReplacementsToString,
6
+ } from "../Uri";
7
+ import {
8
+ Sep7OperationType,
9
+ Sep7Replacement,
10
+ WEB_STELLAR_SCHEME,
11
+ } from "../Types";
12
+
13
+ /**
14
+ * The Sep-7 'tx' operation represents a request to sign
15
+ * a specific XDR TransactionEnvelope.
16
+ *
17
+ * @see https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0007.md#operation-tx
18
+ */
19
+ export class Sep7Tx extends Sep7Base {
20
+ /**
21
+ * Creates a Sep7Tx instance with given transaction.
22
+ *
23
+ * Sets the 'xdr' param as a Stellar TransactionEnvelope in XDR format that
24
+ * is base64 encoded and then URL-encoded.
25
+ *
26
+ * @param {Transaction} transaction a transaction which will be used to set the
27
+ * URI 'xdr' and 'network_passphrase' query params.
28
+ *
29
+ * @returns {Sep7Tx} the Sep7Tx instance.
30
+ */
31
+ static forTransaction(transaction: Transaction): Sep7Tx {
32
+ const uri = new Sep7Tx();
33
+ uri.xdr = transaction.toEnvelope().toXDR().toString("base64");
34
+ uri.networkPassphrase = transaction.networkPassphrase as Networks;
35
+ return uri;
36
+ }
37
+
38
+ /**
39
+ * Creates a new instance of the Sep7Tx class.
40
+ *
41
+ * @constructor
42
+ * @param {URL | string} [uri] - uri to initialize the Sep7 instance.
43
+ */
44
+ constructor(uri?: URL | string) {
45
+ super(uri ?? new URL(`${WEB_STELLAR_SCHEME}${Sep7OperationType.tx}`));
46
+ }
47
+
48
+ /**
49
+ * Returns a deep clone of this instance.
50
+ *
51
+ * @returns {Sep7Tx} a deep clone of this Sep7Tx instance.
52
+ */
53
+ clone(): Sep7Tx {
54
+ return new Sep7Tx(this.uri);
55
+ }
56
+
57
+ /**
58
+ * Returns a URL-decoded version of the uri 'xdr' param.
59
+ *
60
+ * @returns {string | undefined} URL-decoded 'xdr' param if present.
61
+ */
62
+ get xdr(): string | undefined {
63
+ return this.getParam("xdr");
64
+ }
65
+
66
+ /**
67
+ * Sets and URL-encodes the uri 'xdr' param.
68
+ *
69
+ * Deletes the uri 'xdr' param if set as 'undefined'.
70
+ *
71
+ * @param {string | undefined} xdr the uri 'xdr' param to be set.
72
+ */
73
+ set xdr(xdr: string | undefined) {
74
+ this.setParam("xdr", xdr);
75
+ }
76
+
77
+ /**
78
+ * Returns the uri 'pubkey' param.
79
+ *
80
+ * This param specifies which public key the URI handler should sign for.
81
+ *
82
+ * @returns {string | undefined} URL-decoded 'pubkey' param if present.
83
+ */
84
+ get pubkey(): string | undefined {
85
+ return this.getParam("pubkey");
86
+ }
87
+
88
+ /**
89
+ * Sets the uri 'pubkey' param.
90
+ *
91
+ * Deletes the uri 'pubkey' param if set as 'undefined'.
92
+ *
93
+ * This param should specify which public key you want the URI handler
94
+ * to sign for.
95
+ *
96
+ * @param {string | undefined} pubkey the uri 'pubkey' param to be set.
97
+ */
98
+ set pubkey(pubkey: string | undefined) {
99
+ this.setParam("pubkey", pubkey);
100
+ }
101
+
102
+ /**
103
+ * Returns a URL-decoded version of the uri 'chain' param.
104
+ *
105
+ * There can be an optional chain query param to include a single SEP-0007
106
+ * request that spawned or triggered the creation of this SEP-0007 request.
107
+ * This will be a URL-encoded value. The goal of this field is to be
108
+ * informational only and can be used to forward SEP-0007 requests.
109
+ *
110
+ * @returns {string | undefined} URL-decoded 'chain' param if present.
111
+ */
112
+ get chain(): string | undefined {
113
+ return this.getParam("chain");
114
+ }
115
+
116
+ /**
117
+ * Sets and URL-encodes the uri 'chain' param.
118
+ *
119
+ * Deletes the uri 'chain' param if set as 'undefined'.
120
+ *
121
+ * There can be an optional chain query param to include a single SEP-0007
122
+ * request that spawned or triggered the creation of this SEP-0007 request.
123
+ * This will be a URL-encoded value. The goal of this field is to be
124
+ * informational only and can be used to forward SEP-0007 requests.
125
+ *
126
+ * @param {string | undefined} chain the 'chain' param to be set.
127
+ */
128
+ set chain(chain: string | undefined) {
129
+ this.setParam("chain", chain);
130
+ }
131
+
132
+ /**
133
+ * Gets a list of fields in the transaction that need to be replaced.
134
+ *
135
+ * @returns {Sep7Replacement[]} list of fields that need to be replaced.
136
+ */
137
+ getReplacements(): Sep7Replacement[] {
138
+ return sep7ReplacementsFromString(this.getParam("replace"));
139
+ }
140
+
141
+ /**
142
+ * Sets and URL-encodes the uri 'replace' param, which is a list of fields in
143
+ * the transaction that needs to be replaced.
144
+ *
145
+ * Deletes the uri 'replace' param if set as empty array '[]' or 'undefined'.
146
+ *
147
+ * This 'replace' param should be a URL-encoded value that identifies the
148
+ * fields to be replaced in the XDR using the 'Txrep (SEP-0011)' representation.
149
+ * This will be specified in the format of:
150
+ * txrep_tx_field_name_1:reference_identifier_1,txrep_tx_field_name_2:reference_identifier_2;reference_identifier_1:hint_1,reference_identifier_2:hint_2
151
+ *
152
+ * @see https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0011.md
153
+ *
154
+ * @param {Sep7Replacement[]} replacements a list of replacements to set.
155
+ */
156
+ setReplacements(replacements: Sep7Replacement[] | undefined) {
157
+ if (!replacements || replacements.length === 0) {
158
+ this.setParam("replace", undefined);
159
+ return;
160
+ }
161
+ this.setParam("replace", sep7ReplacementsToString(replacements));
162
+ }
163
+
164
+ /**
165
+ * Adds an additional replacement.
166
+ *
167
+ * @param {Sep7Replacement} replacement the replacement to add.
168
+ */
169
+ addReplacement(replacement: Sep7Replacement) {
170
+ const replacements = this.getReplacements();
171
+ replacements.push(replacement);
172
+ this.setReplacements(replacements);
173
+ }
174
+
175
+ /**
176
+ * Removes all replacements with the given identifier.
177
+ *
178
+ * @param {string} id the identifier to remove.
179
+ */
180
+ removeReplacement(id: string) {
181
+ const replacements = this.getReplacements().filter((r) => r.id !== id);
182
+ this.setReplacements(replacements);
183
+ }
184
+
185
+ /**
186
+ * Creates a Stellar Transaction from the URI's XDR and networkPassphrase.
187
+ *
188
+ * @returns {Transaction} the Stellar Transaction.
189
+ */
190
+ getTransaction(): Transaction {
191
+ return new Transaction(this.xdr, this.networkPassphrase || Networks.PUBLIC);
192
+ }
193
+ }
@@ -0,0 +1,9 @@
1
+ export { Sep7Base } from "./Sep7Base";
2
+ export { Sep7Pay } from "./Sep7Pay";
3
+ export { Sep7Tx } from "./Sep7Tx";
4
+ export {
5
+ isValidSep7Uri,
6
+ parseSep7Uri,
7
+ sep7ReplacementsFromString,
8
+ sep7ReplacementsToString,
9
+ } from "./sep7Parser";
@@ -0,0 +1,220 @@
1
+ import { Networks, StrKey, Transaction } from "@stellar/stellar-sdk";
2
+
3
+ import { Sep7Pay, Sep7Tx } from "../Uri";
4
+ import {
5
+ Sep7Replacement,
6
+ Sep7OperationType,
7
+ IsValidSep7UriResult,
8
+ WEB_STELLAR_SCHEME,
9
+ URI_MSG_MAX_LENGTH,
10
+ } from "../Types";
11
+ import {
12
+ Sep7InvalidUriError,
13
+ Sep7UriTypeNotSupportedError,
14
+ } from "../Exceptions";
15
+
16
+ /**
17
+ * Returns true if the given URI is a SEP-7 compliant URI, false otherwise.
18
+ *
19
+ * Currently this checks whether it starts with 'web+stellar:tx' or 'web+stellar:pay'
20
+ * and has its required parameters: 'xdr=' and 'destination=' respectively.
21
+ *
22
+ * @param {string} uri The URI string to check.
23
+ *
24
+ * @returns {IsValidSep7UriResult} returns '{ result: true }' if it's a valid Sep-7
25
+ * uri, returns '{ result: false, reason: "<reason>" }' containing a 'reason' message
26
+ * in case the verification fails.
27
+ */
28
+ export const isValidSep7Uri = (uri: string): IsValidSep7UriResult => {
29
+ if (!uri.startsWith(WEB_STELLAR_SCHEME)) {
30
+ return {
31
+ result: false,
32
+ reason: `it must start with '${WEB_STELLAR_SCHEME}'`,
33
+ };
34
+ }
35
+
36
+ const url = new URL(uri);
37
+
38
+ const type = url.pathname as Sep7OperationType;
39
+ const xdr = url.searchParams.get("xdr");
40
+ const networkPassphrase =
41
+ url.searchParams.get("network_passphrase") || Networks.PUBLIC;
42
+ const destination = url.searchParams.get("destination");
43
+ const msg = url.searchParams.get("msg");
44
+
45
+ if (![Sep7OperationType.tx, Sep7OperationType.pay].includes(type)) {
46
+ return {
47
+ result: false,
48
+ reason: `operation type '${type}' is not currently supported`,
49
+ };
50
+ }
51
+
52
+ if (type === Sep7OperationType.tx && !xdr) {
53
+ return {
54
+ result: false,
55
+ reason: `operation type '${type}' must have a 'xdr' parameter`,
56
+ };
57
+ }
58
+
59
+ if (type === Sep7OperationType.tx && xdr) {
60
+ try {
61
+ new Transaction(xdr, networkPassphrase);
62
+ } catch {
63
+ return {
64
+ result: false,
65
+ reason: `the provided 'xdr' parameter is not a valid transaction envelope on the '${networkPassphrase}' network`,
66
+ };
67
+ }
68
+ }
69
+
70
+ if (type === Sep7OperationType.pay && !destination) {
71
+ return {
72
+ result: false,
73
+ reason: `operation type '${type}' must have a 'destination' parameter`,
74
+ };
75
+ }
76
+
77
+ if (type === Sep7OperationType.pay && destination) {
78
+ // Checks if it's a valid "G", "M" or "C" Stellar address
79
+ const isValidStellarAddress =
80
+ StrKey.isValidEd25519PublicKey(destination) ||
81
+ StrKey.isValidMed25519PublicKey(destination) ||
82
+ StrKey.isValidContract(destination);
83
+
84
+ if (!isValidStellarAddress) {
85
+ return {
86
+ result: false,
87
+ reason:
88
+ "the provided 'destination' parameter is not a valid Stellar address",
89
+ };
90
+ }
91
+ }
92
+
93
+ if (msg?.length > URI_MSG_MAX_LENGTH) {
94
+ return {
95
+ result: false,
96
+ reason: `the 'msg' parameter should be no longer than ${URI_MSG_MAX_LENGTH} characters`,
97
+ };
98
+ }
99
+
100
+ return {
101
+ result: true,
102
+ };
103
+ };
104
+
105
+ /**
106
+ * Try parsing a SEP-7 URI string and returns a Sep7Tx or Sep7Pay instance,
107
+ * depending on the type.
108
+ *
109
+ * @param {string} uri The URI string to parse.
110
+ *
111
+ * @returns {Sep7Tx | Sep7Pay} a uri parsed Sep7Tx or Sep7Pay instance.
112
+ *
113
+ * @throws {Sep7InvalidUriError} if the inputted uri is not a valid SEP-7 URI.
114
+ * @throws {Sep7UriTypeNotSupportedError} if the inputted uri does not have a
115
+ * supported SEP-7 type.
116
+ */
117
+ export const parseSep7Uri = (uri: string): Sep7Tx | Sep7Pay => {
118
+ const isValid = isValidSep7Uri(uri);
119
+ if (!isValid.result) {
120
+ throw new Sep7InvalidUriError(isValid.reason);
121
+ }
122
+
123
+ const url = new URL(uri);
124
+
125
+ const type = url.pathname;
126
+ switch (type) {
127
+ case Sep7OperationType.tx:
128
+ return new Sep7Tx(url);
129
+ case Sep7OperationType.pay:
130
+ return new Sep7Pay(url);
131
+ default:
132
+ throw new Sep7UriTypeNotSupportedError(type);
133
+ }
134
+ };
135
+
136
+ /**
137
+ * String delimiters shared by the parsing functions below.
138
+ */
139
+ const HINT_DELIMITER = ";";
140
+ const ID_DELIMITER = ":";
141
+ const LIST_DELIMITER = ",";
142
+
143
+ /**
144
+ * Takes a Sep-7 URL-decoded 'replace' string param and parses it to a list of
145
+ * Sep7Replacement objects for easy of use.
146
+ *
147
+ * This string identifies the fields to be replaced in the XDR using
148
+ * the 'Txrep (SEP-0011)' representation, which should be specified in the format of:
149
+ * txrep_tx_field_name_1:reference_identifier_1,txrep_tx_field_name_2:reference_identifier_2;reference_identifier_1:hint_1,reference_identifier_2:hint_2
150
+ *
151
+ * @see https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0011.md
152
+ *
153
+ * @param {string} [replacements] a replacements string in the
154
+ * 'Txrep (SEP-0011)' representation.
155
+ *
156
+ * @returns {Sep7Replacement[]} a list of parsed Sep7Replacement objects.
157
+ */
158
+ export const sep7ReplacementsFromString = (
159
+ replacements?: string,
160
+ ): Sep7Replacement[] => {
161
+ if (!replacements) {
162
+ return [];
163
+ }
164
+
165
+ const [txrepString, hintsString] = replacements.split(HINT_DELIMITER);
166
+ const hintsList = hintsString.split(LIST_DELIMITER);
167
+
168
+ const hintsMap: { [id: string]: string } = {};
169
+
170
+ hintsList
171
+ .map((item) => item.split(ID_DELIMITER))
172
+ .forEach(([id, hint]) => (hintsMap[id] = hint));
173
+
174
+ const txrepList = txrepString.split(LIST_DELIMITER);
175
+
176
+ const replacementsList = txrepList
177
+ .map((item) => item.split(ID_DELIMITER))
178
+ .map(([path, id]) => ({ id, path, hint: hintsMap[id] }));
179
+
180
+ return replacementsList;
181
+ };
182
+
183
+ /**
184
+ * Takes a list of Sep7Replacement objects and parses it to a string that
185
+ * could be URL-encoded and used as a Sep-7 URI 'replace' param.
186
+ *
187
+ * This string identifies the fields to be replaced in the XDR using
188
+ * the 'Txrep (SEP-0011)' representation, which should be specified in the format of:
189
+ * txrep_tx_field_name_1:reference_identifier_1,txrep_tx_field_name_2:reference_identifier_2;reference_identifier_1:hint_1,reference_identifier_2:hint_2
190
+ *
191
+ * @see https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0011.md
192
+ *
193
+ * @param {Sep7Replacement[]} [replacements] a list of Sep7Replacement objects.
194
+ *
195
+ * @returns {string} a string that identifies the fields to be replaced in the
196
+ * XDR using the 'Txrep (SEP-0011)' representation.
197
+ */
198
+ export const sep7ReplacementsToString = (
199
+ replacements?: Sep7Replacement[],
200
+ ): string => {
201
+ if (!replacements || replacements.length === 0) {
202
+ return "";
203
+ }
204
+
205
+ const hintsMap: { [id: string]: string } = {};
206
+
207
+ const txrepString = replacements
208
+ .map(({ id, hint, path }) => {
209
+ hintsMap[id] = hint;
210
+
211
+ return `${path}${ID_DELIMITER}${id}`;
212
+ })
213
+ .join(LIST_DELIMITER);
214
+
215
+ const hintsString = Object.entries(hintsMap)
216
+ .map(([id, hint]) => `${id}${ID_DELIMITER}${hint}`)
217
+ .join(LIST_DELIMITER);
218
+
219
+ return `${txrepString}${HINT_DELIMITER}${hintsString}`;
220
+ };
@@ -1,4 +1,5 @@
1
1
  export * from "./camelToSnakeCase";
2
+ export * from "./extractAxiosErrorData";
3
+ export * from "./getResultCode";
2
4
  export * from "./toml";
3
5
  export * from "./url";
4
- export * from "./extractAxiosErrorData";
@@ -1,4 +1,6 @@
1
1
  import { Anchor } from "../Anchor";
2
+ import { Sep6 } from "../Anchor/Sep6";
3
+ import { Sep24 } from "../Anchor/Sep24";
2
4
  import {
3
5
  AnchorTransaction,
4
6
  TransactionStatus,
@@ -329,7 +331,7 @@ export class Watcher {
329
331
  };
330
332
  }
331
333
 
332
- let sepObj;
334
+ let sepObj: Sep6 | Sep24;
333
335
  switch (this.sepType) {
334
336
  case WatcherSepType.SEP6:
335
337
  sepObj = this.anchor.sep6();
@@ -35,18 +35,18 @@ describe("Customer", () => {
35
35
  type: customerType,
36
36
  },
37
37
  });
38
- expect(resp.data.id).toBeTruthy();
39
- const { id } = resp.data;
38
+ expect(resp.id).toBeTruthy();
39
+ const { id } = resp;
40
40
 
41
41
  // Get
42
42
  resp = await sep12.getCustomer({ id, type: customerType });
43
- expect(Object.keys(resp.data).sort()).toEqual(
43
+ expect(Object.keys(resp).sort()).toEqual(
44
44
  ["id", "provided_fields", "fields", "status"].sort(),
45
45
  );
46
- expect(Object.keys(resp.data?.provided_fields).sort()).toEqual(
46
+ expect(Object.keys(resp?.provided_fields).sort()).toEqual(
47
47
  ["first_name", "last_name", "email_address"].sort(),
48
48
  );
49
- expect(Object.keys(resp.data?.fields).sort()).toEqual(
49
+ expect(Object.keys(resp?.fields).sort()).toEqual(
50
50
  [
51
51
  "bank_account_number",
52
52
  "bank_number",
@@ -70,11 +70,11 @@ describe("Customer", () => {
70
70
  },
71
71
  id,
72
72
  });
73
- expect(resp.data.id).toBeTruthy();
73
+ expect(resp.id).toBeTruthy();
74
74
 
75
75
  // Get again, check that the provided fields updated
76
76
  resp = await sep12.getCustomer({ id, type: customerType });
77
- expect(Object.keys(resp.data.fields).length).toBe(0);
77
+ expect(Object.keys(resp.fields).length).toBe(0);
78
78
 
79
79
  // Delete
80
80
  await sep12.delete();
@@ -60,7 +60,7 @@ describe("Anchor Platform Integration Tests", () => {
60
60
  bank_account_number: "12345",
61
61
  },
62
62
  });
63
- expect(sep12Resp.data.id).toBeTruthy();
63
+ expect(sep12Resp.id).toBeTruthy();
64
64
 
65
65
  // SEP-6 deposit
66
66
  const sep6 = anchor.sep6();
@@ -85,7 +85,7 @@ describe("Anchor Platform Integration Tests", () => {
85
85
  },
86
86
  });
87
87
  expect(wResp.id).toBeTruthy();
88
- }, 30000);
88
+ }, 120000);
89
89
 
90
90
  it("SEP-24 should work", async () => {
91
91
  const assetCode = "USDC";