@rango-dev/queue-manager-rango-preset 0.60.1-next.2 → 0.60.1-next.5

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 (38) hide show
  1. package/dist/actions/checkXrplTrustline/checkXrplTrustline.d.ts +5 -0
  2. package/dist/actions/checkXrplTrustline/checkXrplTrustline.d.ts.map +1 -0
  3. package/dist/actions/checkXrplTrustline/index.d.ts +3 -0
  4. package/dist/actions/checkXrplTrustline/index.d.ts.map +1 -0
  5. package/dist/actions/checkXrplTrustline/types.d.ts +9 -0
  6. package/dist/actions/checkXrplTrustline/types.d.ts.map +1 -0
  7. package/dist/actions/checkXrplTrustline/utils.d.ts +13 -0
  8. package/dist/actions/checkXrplTrustline/utils.d.ts.map +1 -0
  9. package/dist/actions/common/produceNextStateForTransaction.d.ts.map +1 -1
  10. package/dist/actions/createTransaction.d.ts.map +1 -1
  11. package/dist/actions/executeXrplTransaction/executeXrplTransaction.d.ts.map +1 -1
  12. package/dist/configs.d.ts.map +1 -1
  13. package/dist/env.d.ts +12 -0
  14. package/dist/env.d.ts.map +1 -0
  15. package/dist/helpers.d.ts +6 -0
  16. package/dist/helpers.d.ts.map +1 -1
  17. package/dist/index.js +1 -1
  18. package/dist/index.js.map +4 -4
  19. package/dist/queue-manager-rango-preset.build.json +1 -1
  20. package/dist/queueDef.d.ts.map +1 -1
  21. package/dist/shared.d.ts.map +1 -1
  22. package/dist/types.d.ts +1 -0
  23. package/dist/types.d.ts.map +1 -1
  24. package/package.json +2 -2
  25. package/src/actions/checkXrplTrustline/checkXrplTrustline.ts +179 -0
  26. package/src/actions/checkXrplTrustline/index.ts +5 -0
  27. package/src/actions/checkXrplTrustline/types.ts +9 -0
  28. package/src/actions/checkXrplTrustline/utils.ts +98 -0
  29. package/src/actions/common/produceNextStateForTransaction.ts +1 -2
  30. package/src/actions/createTransaction.ts +2 -6
  31. package/src/actions/executeXrplTransaction/executeXrplTransaction.ts +53 -139
  32. package/src/actions/scheduleNextStep.ts +1 -1
  33. package/src/configs.ts +3 -8
  34. package/src/env.ts +28 -0
  35. package/src/helpers.ts +45 -27
  36. package/src/queueDef.ts +2 -0
  37. package/src/shared.ts +8 -0
  38. package/src/types.ts +1 -0
@@ -5,14 +5,8 @@ import type {
5
5
  } from '../../types';
6
6
  import type { NextTransactionStateError } from '../common/produceNextStateForTransaction';
7
7
  import type { ExecuterActions } from '@rango-dev/queue-manager-core';
8
- import type {
9
- GenericSigner,
10
- XrplTransaction,
11
- XrplTrustSetTransactionData,
12
- } from 'rango-types';
13
-
14
- import { isXrplTransaction } from 'rango-types';
15
- import { Err } from 'ts-results';
8
+ import type { GenericSigner, XrplTransaction } from 'rango-types';
9
+ import type { Err } from 'ts-results';
16
10
 
17
11
  import {
18
12
  getCurrentStep,
@@ -21,6 +15,10 @@ import {
21
15
  handleSuccessfulSign,
22
16
  } from '../../helpers';
23
17
  import { getCurrentAddressOf, getRelatedWallet } from '../../shared';
18
+ import {
19
+ ensureXrplNamespaceExists,
20
+ ensureXrplTransactionIsValid,
21
+ } from '../checkXrplTrustline';
24
22
  import { checkEnvironmentBeforeExecuteTransaction } from '../common/checkEnvironmentBeforeExecuteTransaction';
25
23
  import {
26
24
  onNextStateError,
@@ -29,12 +27,14 @@ import {
29
27
  } from '../common/produceNextStateForTransaction';
30
28
  import { requestBlockQueue } from '../common/utils';
31
29
 
32
- import { TRUST_LINE_AMOUNT } from './constants';
33
- import { extractFromSymbolAddress } from './helpers';
34
-
35
30
  export async function executeXrplTransaction(
36
31
  actions: ExecuterActions<SwapStorage, SwapActionTypes, SwapQueueContext>
37
32
  ): Promise<void> {
33
+ /*
34
+ *
35
+ * 1. Ensure wallet is connected with a correct address.
36
+ *
37
+ */
38
38
  const checkResult = await checkEnvironmentBeforeExecuteTransaction(actions);
39
39
  if (checkResult.err) {
40
40
  requestBlockQueue(actions, checkResult.val);
@@ -46,6 +46,11 @@ export async function executeXrplTransaction(
46
46
 
47
47
  const swap = getStorage().swapDetails;
48
48
  const currentStep = getCurrentStep(swap)!;
49
+ const currentTransactionFromStorage = getCurrentStepTx(currentStep);
50
+
51
+ const sourceWallet = getRelatedWallet(swap, currentStep);
52
+ const walletAddress = getCurrentAddressOf(swap, currentStep);
53
+
49
54
  const onFinish = () => {
50
55
  if (actions.context.resetClaimedBy) {
51
56
  actions.context.resetClaimedBy();
@@ -63,152 +68,61 @@ export async function executeXrplTransaction(
63
68
  * It will either be Err, indicating process should stop, or Ok, indicating process should continue.
64
69
  */
65
70
  const nextStateResult = produceNextStateForTransaction(actions);
66
- const tx = getCurrentStepTx(currentStep);
67
71
 
68
72
  if (nextStateResult.err) {
69
73
  handleErr(nextStateResult);
70
74
  return;
71
75
  }
72
76
 
73
- // This has been checked inproduceNextStateForTransaction. Checking it in here would make it more resilient for future changes.
74
- if (!tx) {
75
- handleErr(
76
- new Err({
77
- nextStatus: 'failed',
78
- nextStepStatus: 'failed',
79
- message: 'Unexpected Error: tx is null!',
80
- details: undefined,
81
- errorCode: 'CLIENT_UNEXPECTED_BEHAVIOUR',
82
- })
83
- );
84
- return;
85
- }
77
+ // On success, we should update Swap object and also call notifier
78
+ onNextStateOk(actions, nextStateResult.val);
86
79
 
87
- if (!isXrplTransaction(tx)) {
88
- handleErr(
89
- new Err({
90
- nextStatus: 'failed',
91
- nextStepStatus: 'failed',
92
- message:
93
- "Unexpected Error: Expected XRPL transaction but it doesn't match with the structure.",
94
- details: undefined,
95
- errorCode: 'CLIENT_UNEXPECTED_BEHAVIOUR',
96
- })
97
- );
80
+ /*
81
+ *
82
+ * 2. Ensure tx is supported, and namespace exists.
83
+ *
84
+ */
85
+ const transaction = await ensureXrplTransactionIsValid(
86
+ currentTransactionFromStorage
87
+ );
88
+ if (transaction.err) {
89
+ handleErr(transaction);
98
90
  return;
99
91
  }
100
92
 
101
- if (tx.data.TransactionType !== 'Payment') {
102
- handleErr(
103
- new Err({
104
- nextStatus: 'failed',
105
- nextStepStatus: 'failed',
106
- message:
107
- 'Unexpected Error: We only support XRPL transactions with payment type',
108
- details: undefined,
109
- errorCode: 'CLIENT_UNEXPECTED_BEHAVIOUR',
110
- })
111
- );
93
+ const namespace = await ensureXrplNamespaceExists(
94
+ context,
95
+ sourceWallet.walletType
96
+ );
97
+ if (namespace.err) {
98
+ handleErr(namespace);
112
99
  return;
113
100
  }
114
101
 
115
- // On success, we should update Swap object and also call notifier
116
- onNextStateOk(actions, nextStateResult.val);
117
-
118
- const sourceWallet = getRelatedWallet(swap, currentStep);
119
- const walletAddress = getCurrentAddressOf(swap, currentStep);
120
-
121
- const chainId = meta.blockchains?.[tx.blockChain]?.chainId;
102
+ /*
103
+ *
104
+ * 3. Execute transaction
105
+ *
106
+ */
107
+ const chainId = meta.blockchains[transaction.val.blockChain]?.chainId;
122
108
  const walletSigners = await getSigners(sourceWallet.walletType);
123
109
 
124
- const transactionQueue: XrplTransaction[] = [tx];
125
-
126
- // null means it's native token (xrpl).
127
- if (currentStep.toSymbolAddress) {
128
- const [currency, account] = extractFromSymbolAddress(
129
- currentStep.toSymbolAddress
130
- );
131
- if (!currency || !account) {
132
- handleErr(
133
- new Err({
134
- nextStatus: 'failed',
135
- nextStepStatus: 'failed',
136
- message: 'Unexpected token format for XRPL transaction.',
137
- details: undefined,
138
- errorCode: 'CLIENT_UNEXPECTED_BEHAVIOUR',
139
- })
140
- );
141
- return;
142
- }
143
-
144
- // We need to work with namespace instance
145
- const provider = context.hubProvider(sourceWallet.walletType);
146
- const xrplNamespace = provider.get('xrpl');
147
- if (!xrplNamespace) {
148
- handleErr(
149
- new Err({
150
- nextStatus: 'failed',
151
- nextStepStatus: 'failed',
152
- message: 'XRPL is not available on your wallet.',
153
- details: undefined,
154
- errorCode: 'CLIENT_UNEXPECTED_BEHAVIOUR',
155
- })
156
- );
157
- return;
158
- }
159
-
160
- // Check if a trust line exists or not and also have capacity or not, if not, open a new one.
161
-
162
- // TODO: it's better to add some logic around `balance` to ensure we have enough capacity for the trust line. Now we only check it's already open or not.
163
- const lines = await xrplNamespace.accountLines(sourceWallet.address, {
164
- peer: account,
165
- });
166
- const isTruslineAlreadyOpened = lines.some((trustline) => {
167
- return (
168
- trustline.currency === currency &&
169
- trustline.account === account &&
170
- trustline.limit !== '0'
171
- );
172
- });
173
-
174
- if (!isTruslineAlreadyOpened) {
175
- const trustlineTx: XrplTrustSetTransactionData = {
176
- TransactionType: 'TrustSet',
177
- Account: tx.data.Account,
178
- LimitAmount: {
179
- currency: currency,
180
- issuer: account,
181
- value: TRUST_LINE_AMOUNT,
182
- },
183
- };
184
-
185
- transactionQueue.unshift({
186
- ...tx,
187
- data: trustlineTx,
188
- });
189
- }
190
- }
191
-
192
110
  const signer: GenericSigner<XrplTransaction> = walletSigners.getSigner(
193
- tx.type
111
+ transaction.val.type
194
112
  );
195
113
 
196
- for (const transaction of transactionQueue) {
197
- try {
198
- const result = await signer.signAndSendTx(
199
- transaction,
200
- walletAddress,
201
- chainId
202
- );
203
-
204
- // TODO: approval has different meaning for EVM, we may need to add a third type called trustline for the following function.
205
- handleSuccessfulSign(actions, {
206
- isApproval: transaction.data.TransactionType === 'TrustSet',
207
- })(result);
208
- } catch (e) {
209
- handleRejectedSign(actions)(e);
210
- break;
211
- }
114
+ try {
115
+ const result = await signer.signAndSendTx(
116
+ transaction.val,
117
+ walletAddress,
118
+ chainId
119
+ );
120
+
121
+ handleSuccessfulSign(actions, {
122
+ isApproval: transaction.val.data.TransactionType === 'TrustSet',
123
+ })(result);
124
+ } catch (e) {
125
+ handleRejectedSign(actions)(e);
212
126
  }
213
127
 
214
128
  // this works as `finally` for the iterator.
@@ -39,7 +39,7 @@ export function scheduleNextStep({
39
39
  if (!!currentStep && !isFailed) {
40
40
  if (isTxAlreadyCreated(swap, currentStep)) {
41
41
  if (currentStep.fromBlockchain === TransactionType.XRPL) {
42
- schedule(SwapActionTypes.EXECUTE_XRPL_TRANSACTION);
42
+ schedule(SwapActionTypes.CHECK_XRPL_TRUSTLINE);
43
43
  } else {
44
44
  schedule(SwapActionTypes.EXECUTE_TRANSACTION);
45
45
  }
package/src/configs.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  import type { RouteExecutionEvents } from './types';
2
2
 
3
+ import { getApiKeyFromEnvOrNotSet } from './env';
4
+
3
5
  interface Emitter<Events extends Record<string, unknown>> {
4
6
  emit<K extends keyof Events>(type: K, event: Events[K]): void;
5
7
  }
@@ -10,15 +12,8 @@ export interface Configs {
10
12
  emitter?: Emitter<RouteExecutionEvents>;
11
13
  }
12
14
 
13
- /*
14
- * this API key is limited and
15
- * it is only for test purpose
16
- */
17
-
18
- const RANGO_PUBLIC_API_KEY = 'c6381a79-2817-4602-83bf-6a641a409e32';
19
-
20
15
  let configs: Configs = {
21
- API_KEY: RANGO_PUBLIC_API_KEY,
16
+ API_KEY: getApiKeyFromEnvOrNotSet(),
22
17
  BASE_URL: '',
23
18
  };
24
19
 
package/src/env.ts ADDED
@@ -0,0 +1,28 @@
1
+ export function getApiKeyFromEnv(): string | undefined {
2
+ // NOTE: parcel doesn't support for dynamic keys, so we have to do it statically.
3
+ return process.env.REACT_APP_RANGO_API_KEY;
4
+ }
5
+
6
+ /**
7
+ * This is useful when the api key is mandatory and nothing works corectly without api key.
8
+ * You need to first fallback to user's input (widget config), then you can use this to try to find from envs (e.g. widget/app or widget/playground)
9
+ * Then throw an runtime error to panic the program.
10
+ */
11
+ export function getApiKeyFromEnvOrThrow() {
12
+ // NOTE: parcel doesn't support for dynamic keys, so we have to do it statically.
13
+ const value = getApiKeyFromEnv();
14
+ if (value) {
15
+ return value;
16
+ }
17
+
18
+ throw new Error(
19
+ 'Ensure you have set REACT_APP_RANGO_API_KEY in your env variables.'
20
+ );
21
+ }
22
+
23
+ /**
24
+ * You can use this whenever you want to use the api key in initialize process, but mark the key explictly as not set to debug more easily since you should never reach there.
25
+ */
26
+ export function getApiKeyFromEnvOrNotSet(): string {
27
+ return getApiKeyFromEnv() || 'NOT_SET';
28
+ }
package/src/helpers.ts CHANGED
@@ -213,6 +213,7 @@ export const setCurrentStepTx = (
213
213
  currentStep.tonTransaction = null;
214
214
  currentStep.suiTransaction = null;
215
215
  currentStep.xrplTransaction = null;
216
+ currentStep.stellarTransaction = null;
216
217
 
217
218
  const txType = transaction.type;
218
219
  switch (txType) {
@@ -255,6 +256,9 @@ export const setCurrentStepTx = (
255
256
  case TransactionType.XRPL:
256
257
  currentStep.xrplTransaction = transaction;
257
258
  break;
259
+ case TransactionType.STELLAR:
260
+ currentStep.stellarTransaction = transaction;
261
+ break;
258
262
  default:
259
263
  ((x: never) => {
260
264
  throw new Error(`${x} was unhandled!`);
@@ -1060,39 +1064,53 @@ export function isRequiredWalletConnected(
1060
1064
  return { ok: matched, reason: 'account_miss_match' };
1061
1065
  }
1062
1066
 
1067
+ export function updateStorageOnSuccessfulSign(
1068
+ actions: ExecuterActions<SwapStorage, SwapActionTypes, SwapQueueContext>,
1069
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1070
+ signResult: { hash: string; response?: any },
1071
+ data: { isApproval: boolean }
1072
+ ) {
1073
+ const { setTransactionDataByHash } = inMemoryTransactionsData();
1074
+ const { getStorage, context } = actions;
1075
+ const { meta } = context;
1076
+ const swap = getStorage().swapDetails;
1077
+
1078
+ const currentStep = getCurrentStep(swap)!;
1079
+
1080
+ const currentStepNamespace = getCurrentNamespaceOf(swap, currentStep);
1081
+ const explorerUrl = getScannerUrl(
1082
+ signResult.hash,
1083
+ currentStepNamespace.network,
1084
+ meta.blockchains
1085
+ );
1086
+ setStepTransactionIds(
1087
+ actions,
1088
+ signResult.hash,
1089
+ explorerUrl &&
1090
+ (!signResult.response ||
1091
+ (signResult.response && !signResult.response.hashRequiringUpdate))
1092
+ ? {
1093
+ url: explorerUrl,
1094
+ description: data.isApproval ? 'Approve' : 'Swap',
1095
+ }
1096
+ : undefined
1097
+ );
1098
+ // response used for evm transactions to get receipt and track replaced
1099
+ if (signResult.response) {
1100
+ setTransactionDataByHash(signResult.hash, {
1101
+ response: signResult.response,
1102
+ });
1103
+ }
1104
+ }
1105
+
1063
1106
  export function handleSuccessfulSign(
1064
1107
  actions: ExecuterActions<SwapStorage, SwapActionTypes, SwapQueueContext>,
1065
1108
  data: { isApproval: boolean }
1066
1109
  ) {
1067
1110
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
1068
1111
  return ({ hash, response }: { hash: string; response?: any }) => {
1069
- const { setTransactionDataByHash } = inMemoryTransactionsData();
1070
- const { getStorage, next, schedule, context } = actions;
1071
- const { meta } = context;
1072
- const swap = getStorage().swapDetails;
1073
-
1074
- const currentStep = getCurrentStep(swap)!;
1075
-
1076
- const currentStepNamespace = getCurrentNamespaceOf(swap, currentStep);
1077
- const explorerUrl = getScannerUrl(
1078
- hash,
1079
- currentStepNamespace.network,
1080
- meta.blockchains
1081
- );
1082
- setStepTransactionIds(
1083
- actions,
1084
- hash,
1085
- explorerUrl && (!response || (response && !response.hashRequiringUpdate))
1086
- ? {
1087
- url: explorerUrl,
1088
- description: data.isApproval ? 'Approve' : 'Swap',
1089
- }
1090
- : undefined
1091
- );
1092
- // response used for evm transactions to get receipt and track replaced
1093
- if (response) {
1094
- setTransactionDataByHash(hash, { response });
1095
- }
1112
+ const { schedule, next } = actions;
1113
+ updateStorageOnSuccessfulSign(actions, { hash, response }, data);
1096
1114
  schedule(SwapActionTypes.CHECK_TRANSACTION_STATUS);
1097
1115
  next();
1098
1116
  };
package/src/queueDef.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type { SwapQueueDef } from './types';
2
2
 
3
3
  import { checkStatus } from './actions/checkStatus';
4
+ import { checkXrplTrustline } from './actions/checkXrplTrustline';
4
5
  import { createTransaction } from './actions/createTransaction';
5
6
  import { executeTransaction } from './actions/executeTransaction';
6
7
  import { executeXrplTransaction } from './actions/executeXrplTransaction';
@@ -28,6 +29,7 @@ export const swapQueueDef: SwapQueueDef = {
28
29
  [SwapActionTypes.CREATE_TRANSACTION]: createTransaction,
29
30
  [SwapActionTypes.EXECUTE_TRANSACTION]: executeTransaction,
30
31
  [SwapActionTypes.EXECUTE_XRPL_TRANSACTION]: executeXrplTransaction,
32
+ [SwapActionTypes.CHECK_XRPL_TRUSTLINE]: checkXrplTrustline,
31
33
  [SwapActionTypes.CHECK_TRANSACTION_STATUS]: checkStatus,
32
34
  },
33
35
  run: [SwapActionTypes.START],
package/src/shared.ts CHANGED
@@ -119,6 +119,7 @@ export const getCurrentNamespaceOf = (
119
119
  const tonNetwork = step.tonTransaction?.blockChain;
120
120
  const suiNetwork = step.suiTransaction?.blockChain;
121
121
  const xrplNetwork = step.xrplTransaction?.blockChain;
122
+ const stellarNetwork = step.stellarTransaction?.blockChain;
122
123
 
123
124
  if (evmNetwork) {
124
125
  return {
@@ -160,6 +161,11 @@ export const getCurrentNamespaceOf = (
160
161
  namespace: 'XRPL',
161
162
  network: xrplNetwork,
162
163
  };
164
+ } else if (stellarNetwork) {
165
+ return {
166
+ namespace: 'Stellar',
167
+ network: stellarNetwork,
168
+ };
163
169
  } else if (!!step.transferTransaction) {
164
170
  const transferAddress = step.transferTransaction.fromWalletAddress;
165
171
  if (!transferAddress) {
@@ -239,6 +245,7 @@ export const getCurrentWalletTypeAndAddress = (
239
245
  swap.wallets[step.tonTransaction?.blockChain || ''] ||
240
246
  swap.wallets[step.suiTransaction?.blockChain || ''] ||
241
247
  swap.wallets[step.xrplTransaction?.blockChain || ''] ||
248
+ swap.wallets[step.stellarTransaction?.blockChain || ''] ||
242
249
  (step.transferTransaction?.fromWalletAddress
243
250
  ? {
244
251
  address: step.transferTransaction.fromWalletAddress,
@@ -472,6 +479,7 @@ export function calculatePendingSwap(params: {
472
479
  tonTransaction: null,
473
480
  suiTransaction: null,
474
481
  xrplTransaction: null,
482
+ stellarTransaction: null,
475
483
 
476
484
  // front fields
477
485
  hasAlreadyProceededToSign: false,
package/src/types.ts CHANGED
@@ -44,6 +44,7 @@ export enum SwapActionTypes {
44
44
  CREATE_TRANSACTION = 'CREATE_TRANSACTION',
45
45
  EXECUTE_TRANSACTION = 'EXECUTE_TRANSACTION',
46
46
  EXECUTE_XRPL_TRANSACTION = 'EXECUTE_XRPL_TRANSACTION',
47
+ CHECK_XRPL_TRUSTLINE = 'CHECK_XRPL_TRUSTLINE',
47
48
  CHECK_TRANSACTION_STATUS = 'CHECK_TRANSACTION_STATUS',
48
49
  }
49
50